120

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

我真正想要的是场景图MyLib.Scenegraph和其他类MyLib.Scenegraph.*,但似乎唯一的方法是让所有其他类Scenegraph成为 Scenegraph.cs 文件中的内部类,这太笨拙了.

相反,我将它组织为Mylib.Scenegraph.ScenegraphMyLib.Scenegraph.*,哪种有效,但我发现 Visual Studio 在某些情况下会混淆我是指类还是命名空间。

有没有一种很好的方法来组织这个包,以便用户方便而不会将我的所有代码混在一起,造成无法维护的混乱?

4

9 回答 9

129

我不建议您像命名空间一样命名一个类,请参阅这篇文章

框架设计指南在第 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 和 Bar.Foo 之间是模棱两可的。真可惜。我想我会通过完全限定名称来解决这个问题:

   class C { Foo.Foo foo; } 

这现在给出了歧义错误“<strong>Foo in Foo.Foo is ambiguous between Foo.Foo and Bar.Foo”。我们仍然不知道第一个 Foo 指的是什么,在我们弄清楚之前,我们甚至都不会费心去弄清楚第二个指的是什么。

于 2013-09-11T01:50:37.147 回答
23

正如其他人所说,为命名空间和类赋予相同的名称可能会使编译器感到困惑。

那怎么命名呢?

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

如果命名空间只有一个类(因此很想给它同名),命名命名空间ClassName NS。至少微软是这样命名他们的命名空间的。

于 2018-01-05T12:23:46.717 回答
11

我建议您按照我得到的建议microsoft.public.dotnet.languages.csharp使用MyLib.ScenegraphUtil.Scenegraphand MyLib.ScenegraphUtil.*.

于 2014-07-03T09:34:10.653 回答
10

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

例如,就我而言,我不是做出这样决定的人,因此我需要找到一种方法让它发挥作用。

因此,对于那些无法更改命名空间名称或类名的人来说,这是一种让您的代码工作的方法。

// 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 的“混乱”消失了。

注意: 如果在您的控制之下,您应该避免这种命名冲突。仅当您无法控制相关的类和命名空间时,才应使用上述技术。

于 2020-05-24T22:20:47.470 回答
7

CA1724: Type Names Should Not Match Namespaces...

基本上,如果您遵循代码分析进行正确编码,则此规则表示不要做您想做的事情。代码分析在帮助您发现潜在问题方面非常有用。

于 2013-09-11T02:03:05.640 回答
5

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

“......但似乎唯一的方法是在 Scenegraph.cs 文件中使所有其他类成为 Scenegraph 的内部类,这太笨拙了。”

对于一堆场景,这确实是更好的实现。但是,我同意将所有代码放在同一个 .cs 文件中很烦人(至少可以这么说)。

您可以通过使基类成为“部分类”来解决它,然后继续在自己的文件上创建内部类(请记住,他们必须声明基类补码,然后继续使用特定的内部类对于该文件)。

就像是...

场景图.cs:

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

依赖类.cs:

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

我确实认为这是您可以更接近于干净地实现内部类,而不必将所有内容都放在一个巨大而凌乱的文件中。

于 2019-04-12T20:41:22.497 回答
4

当它是命名空间的主类时会发生这种情况。因此,将命名空间放入库中是一种动机,如果将“Lib”添加到命名空间名称中,问题就会消失......

namespace SocketLib
{
    class Socket
    {
于 2019-09-17T08:02:57.433 回答
4

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

以下是svick对 Software Engineering Stack Exchange 上相关问题“Same class and namespace name”的回答中的一些额外命名建议:

没错,您不应该将命名空间命名为与其包含的类型相同的名称。我认为您可以使用几种方法:

  • 复数:Model.DataSources.DataSource

如果命名空间的主要目的是包含继承自相同基类型或实现相同接口的类型,则此方法尤其适用。

  • 缩短:Model.QueryStorage

如果命名空间仅包含少量类型,那么您可能根本不需要该命名空间。

  • 企业化:Model.ProjectSystem.Project

这尤其适用于作为产品重​​要组成部分的功能,因此它们应该有自己的名字。

(请注意,上述答案使用Model.DataSource.DataSourceModel.QueryStorage.QueryStorage.Model.Project.Project作为示例,而不是MyLib.Scenegraph.Scenegraph。)

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

于 2019-07-24T16:51:21.073 回答
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。名称空间中的点不是句法。整个字符串是一个标记,而不是由点分隔的单词。

运行 .Net 4.6 的 VS 2015 展示了这种行为

于 2015-11-30T21:34:23.750 回答