C# 命名空间别名 - 有什么意义?

问题描述 投票:0回答:12

人们会在何时何地使用命名空间别名,例如

 using someOtherName =  System.Timers.Timer;

在我看来,这只会给理解语言带来更多混乱。

c# namespaces
12个回答
196
投票

那是类型别名,而不是命名空间别名;消除歧义很有用 - 例如,反对:

using WinformTimer = System.Windows.Forms.Timer;
using ThreadingTimer = System.Threading.Timer;

(ps:感谢您的选择

Timer
;-p)

否则,如果您在同一个文件中同时使用

System.Windows.Forms.Timer
System.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) { }
    }
}

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();

它可以节省大量的打字时间,并且可以使代码更易于阅读。


20
投票

除了提到的示例之外,在重复引用泛型类型时,类型别名(而不是命名空间别名)也很方便:

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
投票

简洁。

在共享类型名称的命名空间之间提供清晰度有一些附带好处,但本质上它只是糖。


7
投票

我总是在这种情况下使用它

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

其中

Utility
否则会有不同的上下文(如
MyBaseNamespace.MySubNamespace.MySubSubNamespace.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(); 

我们已经定义了一些别名必须如何命名的准则,并且每个人都在使用它们。


3
投票

我发现别名在单元测试中非常有用。当您编写单元测试时,通常的做法是将测试主题声明为

MyClass myClassUT;

成为

myClassUT
主题 Under Test。但是,如果您想为具有静态方法的静态类编写单元测试怎么办?然后你可以创建一个像这样的别名:

using MyStaticClassUT = Namespace.MyStaticClass;

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

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

并且您永远不会忘记被测试的主题是什么。


3
投票

从某种意义上说,在 Visual Studio 中编码时它确实非常方便。

用例:假设我只需要使用几个类,例如

SqlConnection
来自命名空间
System.Data
。通常情况下,我将导入 *.cs 文件顶部的
System.Data.SqlClient
命名空间,如下所示:

using System.Data;

现在看看我的智能感知。在代码编辑器中输入时,它的数量急剧增加,有大量的类可供选择。我根本不会使用一大堆课程:

enter image description here

所以我宁愿在 *.cs 文件顶部使用别名并获得清晰的智能感知视图:

using SqlDataCon = System.Data.SqlClient.SqlConnection

现在看看我的智能感知视图。超级清晰超级干净。

enter image description here


2
投票

我知道的一个原因;当导入的命名空间发生名称冲突时,它允许您使用较短的名称。 示例:

如果您在访问

using System.Windows.Forms;
时在同一个文件中声明了
using System.Windows.Input;
ModifierKeys
,您可能会发现名称
ModifierKeys
位于
System.Windows.Forms.Control
System.Windows.Input
命名空间中。 因此,通过声明
using Input = System.Windows.Input;
,您可以通过
System.Windows.Input.ModifierKeys
获得
Input.ModifierKeys

我不是 C# 爱好者,但别名命名空间对我来说似乎是“最佳实践”。这样您就知道自己得到了什么,并且仍然不必输入太多内容。


1
投票

您可以使用它们非常轻松地修改代码。

例如:

#if USE_DOUBLES
using BNumber = System.Double;
#else
using BNumber = System.Single;
#endif

public void BNumber DoStuff(BNumber n) {
    // ...
}
public void BNumber DoStuff2(BNumber n) {
    // ...
}
public void BNumber DoStuff3(BNumber n) {
    // ...
}

通过简单更改指令,您可以决定整个代码是否适用于

float
double


0
投票

已经提到过,但另一个非常有用的例子是避免非常长而混乱的类名。

这可以改变这个:

int bySortWeight(KeyValuePair<Recipe, ItemDrop.ItemData> a, KeyValuePair<Recipe, ItemDrop.ItemData> b) => a.Key.m_listSortWeight.CompareTo(b.Key.m_listSortWeight);
int byName(KeyValuePair<Recipe, ItemDrop.ItemData> a, KeyValuePair<Recipe, ItemDrop.ItemData> b) => a.Key.m_item.m_itemData.m_shared.m_name.CompareTo(b.Key.m_item.m_itemData.m_shared.m_name);

变得更加清洁:

using KVP = System.Collections.Generic.KeyValuePair<Recipe, ItemDrop.ItemData>;

int bySortWeight(KVP a, KVP b) => a.Key.m_listSortWeight.CompareTo(b.Key.m_listSortWeight);
int byName(KVP a, KVP b) => a.Key.m_item.m_itemData.m_shared.m_name.CompareTo(b.Key.m_item.m_itemData.m_shared.m_name);

Piktiv 和朋友共进晚餐

© www.soinside.com 2019 - 2024. All rights reserved.