C # 名称空间别名——有什么意义呢?

在什么地方或什么时候使用名称空间别名

 using someOtherName =  System.Timers.Timer;

在我看来,这只会给理解这门语言增加更多的困惑。

75778 次浏览

That is a type alias, not a namespace alias; it is useful to disambiguate - for example, against:

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

(ps: thanks for the choice of Timer ;-p)

Otherwise, if you use both System.Windows.Forms.Timer and System.Timers.Timer in the same file you'd have to keep giving the full names (since Timer could be confusing).

It also plays a part with extern aliases for using types with the same fully-qualified type name from different assemblies - rare, but useful to be supported.


Actually, I can see another use: when you want quick access to a type, but don't want to use a regular using because you can't import some conflicting extension methods... a bit convoluted, but... here's an example...

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) { }
}
}

It is very useful when you have multiple classes with the same name in multiple included namespaces. For example...

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


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

You can use aliases to make the compiler happy and to make things more clear for you and others on your team:

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


/* ... */


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

I always use it in situations like this

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

where Utility would otherwise have a different context (like MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility), but I expect/prefer Utility to always point to that one particular class.

Brevity.

There are fringe benefits to provide clarity between namespaces which share type names, but essentially it's just sugar.

I use it when I've got multiple namespaces with conflicting sub namespaces and/or object names you could just do something like [as an example]:

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


...


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

Which would otherwise have to be written:

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


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

It saves a ton of typing and can be used to make code a lot easier to read.

We have defined namespace aliases for all of our namespaces. This makes it very easy to see where a class comes from, e.g:

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.

and

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

We have defined some guidelines how the aliases must be named and everyone is using them.

In addition to the examples mentioned, type aliases (rather than namespace aliases) can be handy when repeatedly referring to generic types:

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


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

Versus:

using FooDict = Dictionary<string, SomeClassWithALongName>;


FooDict foo = new FooDict();


private void DoStuff(FooDict dict) {}

I find the aliases very useful in unit testing. When you are writing unit tests, it is a common practice to declare the subject to test as

MyClass myClassUT;

being myClassUT the subject Under Test. But what if you want to write unit tests for a static class with static methods? Then you can create an alias like this:

using MyStaticClassUT = Namespace.MyStaticClass;

Then you can write your unit tests like this:

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

and you never loose sight of what the subject under test is.

In one way it is really handy while coding in Visual Studio.

Use-case: Let's say I've to use only few classes e.g. SqlConnection from a namespace System.Data. In normal course I'll import the System.Data.SqlClient namespace at the top of the *.cs file as shown below:

using System.Data;

Now look at my intellisense. It is heavily proliferated with whole lot of classes to choose from while typing in code editor. I'm not going to use whole bunch of classes at all:

enter image description here

So I would rather use an alias at the top of my *.cs file and get a clear intellisense view:

using SqlDataCon = System.Data.SqlClient.SqlConnection

Now look at my intellisense view. It is super-clear and super-clean.

enter image description here

One reason I know; It lets you use shorter names when you have name collisions from imported namespaces. Example:

If you declared using System.Windows.Forms; and using System.Windows.Input; in the same file when you go to access ModifierKeys you might find that the name ModifierKeys is in both the System.Windows.Forms.Control and System.Windows.Input namespaces. So by declaring using Input = System.Windows.Input; you can then get System.Windows.Input.ModifierKeys via Input.ModifierKeys.

I'm not a C# buff but aliasing namespace seems like "best practise" to me. That way you know what you're getting and still don't have to type too much more.

You can use them to modify a code very easily.

For example:

#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) {
// ...
}

By the simple change in of the directive you can decide if your whole code works in float or double.