命名空间和具有相同名称的类?

时间:2013-09-11 01:44:23

标签: c# class namespaces

我正在组织一个库项目,我有一个名为Scenegraph的中央管理器类和一大堆其他类,它们存在于Scenegraph命名空间中。

我真正喜欢的是场景图是MyLib.Scenegraph而其他类是MyLib.Scenegraph.*,但似乎唯一的方法就是让所有其他类成为内在

相反,我把它组织为ScenegraphMylib.Scenegraph.Scenegraph,这种方式有用,但我发现Visual Studio在某些条件下会混淆我是否指的是类或命名空间。

有没有一种很好的方法来组织这个软件包,这样对于用户而言,如果没有将我的所有代码混淆在一起,就会在一个难以维护的混乱中变得方便?

9 个答案:

答案 0 :(得分:96)

我不建议您将类命名为类名称,请参阅this

  

框架设计指南在3.4节中说“不要使用   命名空间的相同名称和该命名空间中的类型“。那就是:

namespace MyContainers.List 
{ 
    public class List { … } 
}
  

为什么这么糟糕?哦,让我数数一下。

     

你可以进入你认为自己所指的情境   一件事,但实际上指的是别的东西。假设你   在这种不幸的情况下结束:你正在写Blah.DLL和   导入Foo.DLL和Bar.DLL,遗憾的是,它们都有一个类型   叫做Foo:

// Foo.DLL: 
namespace Foo { public class Foo { } }

// Bar.DLL: 
namespace Bar { public class Foo { } }

// Blah.DLL: 
namespace Blah  
{   
using Foo;   
using Bar;   
class C { Foo foo; } 
}
  

编译器出错。 “Foo”在Foo.Foo和Foo之间是不明确的   Bar.Foo。糟糕。我想我会通过完全限定名称来解决这个问题:

   class C { Foo.Foo foo; } 
  

这现在给出了模糊性错误“ Foo in   Foo.Foo在Foo.Foo和Bar.Foo之间是不明确的“。我们还是不知道   第一个Foo指的是什么,直到我们能够弄明白,我们   甚至懒得试图找出第二个引用的内容。

答案 1 :(得分:8)

为命名空间赋予相同的名称,并且类可能会像其他人所说的那样混淆编译器。

如何命名?

如果命名空间有多个类,那么找一个定义所有这些类的名称。

如果命名空间只有一个类(因此诱使它给出相同的名称),请将命名空间命名为 ClassName NS 。这就是微软至少为其命名空间命名的方式。

答案 2 :(得分:7)

我建议您按照microsoft.public.dotnet.languages.csharp上的建议使用MyLib.ScenegraphUtil.ScenegraphMyLib.ScenegraphUtil.*

答案 3 :(得分:5)

CA1724: Type Names Should Not Match Namespaces ...

基本上,如果您按照代码分析进行正确的编码,则该规则表示不执行您要执行的操作。代码分析非常有用帮助您找到潜在的问题。

答案 4 :(得分:5)

即使我同意其他答案,即您不应将类的名称与名称空间相同。有时候,您可能无法遵守此类要求。

例如,在我而言,我不是做出这样决定的人,因此,我需要找到一种使之起作用的方法。

因此,对于那些无法更改名称空间名称或类名称的人,这里是使代码正常工作的一种方式。

// Foo.DLL: 
namespace Foo { public class Foo { } }

// Bar.DLL: 
namespace Bar { public class Foo { } }

// Blah.DLL: 
namespace Blah
{
    using FooNSAlias = Foo;//alias
    using BarNSAlias = Bar;//alias
    class C { FooNSAlias.Foo foo; }//use alias to fully qualify class name
}

基本上,我创建了名称空间“别名”,这使我能够完全限定该类,而Visual Studio“混乱”消失了。

注意: 如果可以控制,则应避免这种命名冲突。 仅当您不受有关类和名称空间的控制时,才应使用上述技术。

答案 5 :(得分:4)

加我2美分:

我有以下课程:

namespace Foo {
    public struct Bar {
    }
    public class Foo {
        //no method or member named "Bar"
    }
}

客户端是这样写的:

using Foo;

public class Blah {
    public void GetFoo( out Foo.Bar[] barArray ) {
    }
}

原谅错误GetFoo没有返回输出而不是使用out参数,编译器无法解析数据类型Foo.Bar []。它返回错误:找不到类型或命名空间Foo.Bar。

似乎在尝试编译时,它将Foo解析为类,并且没有在类Foo中找到嵌入式类Bar。它也找不到名为Foo.Bar的命名空间。它无法在名称空间Foo中查找类Bar。名称空间中的点不是语法。整个字符串是一个标记,而不是由点分隔的单词。

此行为由VS 2015运行.Net 4.6

展示

答案 6 :(得分:0)

旧帖子,但在这里我想出另一种可能对某人有帮助的想法:

“ ...但是看来,这样做的唯一方法是将所有其他类作为Scenegraph.cs文件中的Scenegraph的内部类,这太笨拙了。”

对于许多场景,这确实是更好的实现。但是,我同意将所有代码都放在同一个.cs文件中令人讨厌(至少可以这样说)。

您可以通过将基类设为“局部类”来解决它,然后继续在自己的文件上创建内部类(只记得它们必须声明基类的补码,然后继续该文件的特定内部类)。

类似...

Scenegraph.cs:

namespace MyLib
{
    public partial class Scenegraph
    {
        //Scenegraph specific implementations
    }
}

DependentClass.cs:

namespace MyLib
{
    public partial class Scenegraph
    {
        public class DependentClass
        {
            //DependentClass specific implementations
        }
    }
}

我确实认为,这更接近于清晰地实现内部类,而不必使一个庞大且混乱的文件中的所有内容杂乱无章。

答案 7 :(得分:0)

正如其他人所说,避免将类命名为其名称空间是一个好习惯。

以下是来自an answer by svick的一些附加命名建议,有关此问题的答案是“软件工程堆栈交换”上的“类和名称空间名称相同”:

  

您是对的,不应将名称空间命名为与类型相同的名称   它包含了。我认为您可以使用几种方法:

     
      
  • 多元化:Model.DataSources.DataSource
  •   
     

如果命名空间的主要目的是   包含从相同基本类型继承的类型或实现   相同的界面。

     
      
  • 缩短:Model.QueryStorage
  •   
     

如果名称空间仅包含少量类型,那么您可能不会   完全需要那个名称空间。

     
      
  • 具有企业精神:Model.ProjectSystem.Project
  •   
     

这特别适用于您的重要组成部分的功能   产品,所以他们应有自己的名字。

(请注意,以上答案以'''python im = cv2.imread(image_path) im = im.astype(np.float32, copy=False) input_image = im input_image = np.array(input_image, dtype=np.uint8) input_image = np.expand_dims(input_image, axis=0) interpreter.set_tensor(input_details[0]['index'], input_image) interpreter.invoke() output_data = interpreter.get_tensor(output_details[0]['index']) output_data2 = interpreter.get_tensor(output_details[1]['index']) output_data3 = interpreter.get_tensor(output_details[2]['index']) min_1 = -8.198164939880371 max_1 = 8.798029899597168 scale = (max_1 - min_1)/ 255.0 min_2 = -9.77856159210205 max_2 = 10.169703483581543 scale_2 = (max_2 - min_2) / 255.0 min_3 = -14.382895469665527 max_3 = 11.445544242858887 scale_3 = (max_3 - min_3) / 255.0 output_data = (output_data ) * scale + min_1 output_data2 = (output_data2) * scale_2 + min_2 output_data3 = (output_data3) * scale_3 + min_3 Model.DataSource.DataSourceModel.QueryStorage.QueryStorage.为例,而不是Model.Project.Project。)

(我还发现此处其他答案中的其他命名建议很有帮助。)

答案 8 :(得分:0)

它是名称空间的主类时发生。因此,将名称空间放入库中是一种动机,然后如果在名称空间名称中添加“ Lib”,问题就消失了。

namespace SocketLib
{
    class Socket
    {