C#命名空间别名 - 有什么用处?

115

在哪里或何时需要使用命名空间别名?

 using someOtherName =  System.Timers.Timer;

我认为这只会增加理解该语言的混乱。


11
在C#中,全局使用using int = System.Int32怎么样?很有用吧?这与其他地方可以利用相同的用途。 - nawfal
@nawfal 我认为类型别名是不可导出的。这意味着您不能定义像 using int = System.Int32 这样的东西,并在声明文件之外的其他地方使用它。因此,这个 intInt32 的别名可能通过其他方式实现,或者是编译器/运行时中的特殊事物。 - KFL
1
@KFL 这是真的,但它们提供的好处性质相同。 - nawfal
1
@nawfal,你关于“使用int = System.Int32”的论点是错误和误导性的——它是错误的,因为int别名并不是按照你所描述的方式实现的。它是误导性的,因为你暗示类型别名可以像int覆盖Int32一样在全局范围内使用。 - KFL
3
我并没有暗示两者都有,我只是说明为什么给类型取一个自定义名称可能很有用。 - nawfal
11个回答

190
那是一个类型别名,而不是命名空间别名;它有助于消除歧义 - 例如,与之相对的是:
using WinformTimer = System.Windows.Forms.Timer;
using ThreadingTimer = System.Threading.Timer;

(附注:感谢选择“计时器”;-p)
否则,如果您在同一文件中同时使用System.Windows.Forms.TimerSystem.Threading.Timer,那么您必须始终给出完整的名称(因为Timer可能会引起混淆)。
这也与使用具有相同完全限定类型名称的类型的extern别名有关 - 这种情况很少见,但支持这种功能非常有用。
实际上,我可以看到另外一种用法:当你想要快速访问某个类型,但又不想使用常规的using,因为你不能导入一些冲突的扩展方法。有点复杂,但这里有一个例子:
namespace RealCode {
    //using Foo; // can't use this - it breaks DoSomething
    using Handy = Foo.Handy;
    using Bar;
    static class Program {
        static void Main() {
            Handy h = new Handy(); // prove available
            string test = "abc";            
            test.DoSomething(); // prove available
        }
    }
}
namespace Foo {
    static class TypeOne {
        public static void DoSomething(this string value) { }
    }
    class Handy {}
}
namespace Bar {
    static class TypeTwo {
        public static void DoSomething(this string value) { }
    }
}

8
它可以用于给命名空间或类型名称取别名。 - Sean Bright
2
@Sean:是的,但是给出的例子是针对一个类型的。 - Marc Gravell
@lupefiasco:方便之处在于OP选择了System.Timers.Timer ;-p - Marc Gravell
啊,我以为你在指的是概念而不是具体的例子。对不起我的错误。 - Sean Bright

29

当我有多个命名空间具有冲突的子命名空间和/或对象名称时,我会使用它,你可以像这样做 [举例]:

using src = Namespace1.Subspace.DataAccessObjects;
using dst = Namespace2.Subspace.DataAccessObjects;

...

src.DataObject source = new src.DataObject();
dst.DataObject destination = new dst.DataObject();

否则必须编写以下内容:

Namespace1.Subspace.DataAccessObjects.DataObject source = 
  new Namespace1.Subspace.DataAccessObjects.DataObject();

Namespace2.Subspace.DataAccessObjects.DataObject dstination = 
  new Namespace2.Subspace.DataAccessObjects.DataObject();

这可以减少大量的输入,并且可以用来使代码更易读。


19

除了提到的例子之外,当需要反复引用通用类型时,类型别名(而不是命名空间别名)也很方便:

Dictionary<string, SomeClassWithALongName> foo = new Dictionary<string, SomeClassWithALongName>();

private void DoStuff(Dictionary<string, SomeClassWithALongName> dict) {}

对比:

using FooDict = Dictionary<string, SomeClassWithALongName>;

FooDict foo = new FooDict();

private void DoStuff(FooDict dict) {}

9

简洁性。

为共享类型名称的命名空间提供清晰度是其附带好处,但本质上它只是糖果。


它清晰地显示了你正在使用哪个符号。如果你不想定义一个新名称,它不仅是语法糖,而且有点啰嗦。 - Earth Engine

7

我经常在这种情况下使用它

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

在其他情况下(例如MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility),Utility将具有不同的上下文,但我期望/更喜欢Utility始终指向那个特定的类。


6

当您在多个包含命名空间中有多个具有相同名称的类时,它非常有用。例如...

namespace Something.From.SomeCompanyA {
    public class Foo {
        /* ... */
    }
}

namespace CompanyB.Makes.ThisOne {
    public class Foo {
        /* ... */
    }
}

您可以使用别名来让编译器更加顺畅,并使您和团队中的其他人更加清晰明了:

using CompanyA = Something.From.CompanyA;
using CompanyB = CompanyB.Makes.ThisOne;

/* ... */

CompanyA.Foo f = new CompanyA.Foo();
CompanyB.Foo x = new CompanyB.Foo();

3
我们已经为所有的命名空间定义了别名。这使得很容易看出一个类来自哪里,例如:
using System.Web.WebControls;
// lots of other using statements

// contains the domain model for project X
using dom = Company.ProjectX.DomainModel; 
// contains common web functionality
using web = Company.Web;
// etc.

并且。
// User from the domain model
dom.User user = new dom.User(); 
// Data transfer object
dto.User user = new dto.User(); 
// a global helper class
utl.SomeHelper.StaticMethod(); 
// a hyperlink with custom functionality
// (as opposed to System.Web.Controls.HyperLink)
web.HyperLink link = new web.HyperLink(); 

我们已经定义了一些指南,规定别名的命名方式,每个人都在使用它们。

1
你不觉得别名常常与使用它的上下文相关,而不是对象的物理位置有更多关系吗? - BenAlabaster

2
我知道的一个原因是,当你在导入命名空间时遇到名称冲突时,它可以让你使用更短的名称。例如:如果你在同一文件中声明了using System.Windows.Forms;using System.Windows.Input;,当你想要访问ModifierKeys时,你可能会发现ModifierKeys这个名称在System.Windows.Forms.ControlSystem.Windows.Input这两个命名空间中都存在。因此,通过声明using Input = System.Windows.Input;,你可以通过Input.ModifierKeys来获取System.Windows.Input.ModifierKeys
我不是C#专家,但给命名空间取别名似乎是最佳实践。这样你就知道你得到了什么,而且还不必输入太多字符。

2
在某种程度上,在Visual Studio中编码时,它确实非常方便。
使用情境:假设我只需要使用一些类,例如System.Data命名空间中的SqlConnection。通常情况下,我会在*.cs文件的顶部导入System.Data.SqlClient命名空间,如下所示:
using System.Data;

现在看一下我的智能感知。在输入代码编辑器时,有大量的类可供选择。我根本不会使用这么多类:

enter image description here

因此,我宁愿在我的 *.cs 文件顶部使用一个别名,并获得清晰的智能感知视图:
using SqlDataCon = System.Data.SqlClient.SqlConnection

现在看看我的智能感知视图。它非常清晰和干净。

enter image description here


2
我发现在单元测试中使用别名非常有用。当你编写单元测试时,通常会声明要测试的主题为:
MyClass myClassUT;

假设你想为一个包含静态方法的静态类编写单元测试,该类名为myClassUT。那么你可以创建一个别名,如下所示:

using MyStaticClassUT = Namespace.MyStaticClass;

然后,您可以像这样编写单元测试:

然后,您可以像这样编写单元测试:

public void Test()
{
    var actual = MyStaticClassUT.Method();
    var expected = ...
}

并且您永远不会失去对测试主题的关注。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接