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

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

我真正希望的是场景图是 MyLib.Scenegraph,而其他类是 MyLib.Scenegraph.*,但似乎唯一的方法是把所有其他类内部的 Scenegraph类放在 Scenegrap.cs 文件中,这实在太笨拙了。

相反,我将其组织为 Mylib.Scenegraph.ScenegraphMyLib.Scenegraph.*,这两种方法都很有效,但是我发现 Visual Studio 在某些情况下会混淆,不知道我指的是类还是名称空间。

有没有一个好的方法来组织这个包,使用户方便,而不是把我所有的代码放在一起成为一个不可维护的烂摊子?

115806 次浏览

我不建议您将类命名为它的名称空间,参见 这篇文章

框架设计指南第3.4节说“不要使用 命名空间和该命名空间中的类型使用相同的名称”,即:

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

为什么是坏事? 哦,让我来数数。

你可以让自己陷入你认为自己在提及的情况 但实际上指的是别的东西。假设你 最终会出现这种不幸的情况: 您正在编写 Blah.DLL 和 导入 Foo.DLL 和 Bar.DLL,不幸的是,它们都有一个类型 叫做福:

// 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; }
}

编译器给出一个错误。 < strong > “ Foo”在 Foo. Foo 和 Bummer。我想我可以通过完全修饰名称来解决这个问题:

   class C { Foo.Foo foo; }

现在给出歧义错误“ < strong > Foo in Foo。 Foo 在 Foo。 Foo 和 Bar。 Foo 之间是模糊的。我们仍然不知道 第一个 Foo 指的是什么,在我们弄清楚之前,我们 别费心去想第二个是什么意思。

CA1724: Type Names Should Not Match Namespaces ...

基本上,如果您遵循代码分析来进行正确的编码,这条规则告诉您不要做您正在尝试做的事情。代码分析是 非常有用,可以帮助您找到 潜力问题。

我建议你按照我在 microsoft.public.dotnet.languages.csharp上得到的建议使用 MyLib.ScenegraphUtil.ScenegraphMyLib.ScenegraphUtil.*

我再补充一点:

我有以下课程:

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。酒吧[]。它正在返回错误: 无法找到类型或命名空间 Foo。酒吧。

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

这种行为在 VS 2015的运行中得到了体现.Net 4.6

给名称空间和类命名相同的名称可能会像其他人说的那样混淆编译器。

那怎么命名呢?

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

如果 名称空间只有一个类(因此容易使用相同的名称)将名称空间命名为 ClassName < strong > NS 。微软至少是这样命名它们的名称空间的。

这是一篇老文章,不过我还有另外一个可能对某些人有帮助的想法:

但似乎唯一的办法就是把所有其他类放在 Scenegrap.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
}
}
}

我确实认为,这是一个更接近于拥有干净的内部类实现,同时又不必在一个巨大而混乱的文件中将所有东西都弄得乱七八糟的方法。

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

下面是 Svick 的回答中的一些 附加命名建议,以及软件工程堆栈交换中的一个相关问题“同一个类和名称空间名称”:

您说得对,不应该将命名空间命名为与类型相同的命名空间 我认为你可以使用以下几种方法:

  • Pluralize: Model

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

  • 缩写: 模型。查询存储

如果命名空间只包含少量类型,则可能不包含 完全需要这个名称空间。

  • 创建企业: 模型。项目系统。项目

这尤其适用于您的 产品,所以他们应该有自己的名字。

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

namespace SocketLib
{
class Socket
{

尽管我同意 您不应该将类命名为与命名空间相同的名称中的其他答案,但有些时候你不能遵守这些要求。

以我为例,我不是那个做出这样决定的人,因此我需要找到一种方法来使它工作。

因此,对于那些不能更改名称空间名称或类名称的人来说,这里提供了一种使代码工作的方法。

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

注意: 如果命名冲突在您的控制之下,那么您应该避免这种命名冲突。 只有在不能控制所涉及的类和命名空间时,才应该使用上述技术。