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

时间:2009-02-02 22:38:22

标签: c# namespaces

我一直在努力了解有关C#语言的更多信息,但是我无法看到使用命名空间别名的情况,例如

 using someOtherName =  System.Timers.Timer;

在我看来,它只会增加对理解语言的困惑。 有人可以解释一下。

由于

11 个答案:

答案 0 :(得分:137)

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

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

(ps:感谢选择Timer ;-p)

否则,如果您在同一个文件中同时使用System.Windows.Forms.TimerSystem.Timers.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) { }
    }
}

答案 1 :(得分:24)

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

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

它节省了大量的输入,可以用来使代码更容易阅读。

答案 2 :(得分:16)

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

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

答案 3 :(得分:7)

简洁。

在共享类型名称的命名空间之间提供清晰度有很多好处,但实质上它只是糖。

答案 4 :(得分:6)

我总是在这样的情况下使用它

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

其中Utility会有不同的上下文(例如MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility),但我希望/更喜欢Utility始终指向一个特定的类。

答案 5 :(得分:4)

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

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

答案 6 :(得分: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(); 

我们已经定义了一些指导如何命名别名并且每个人都在使用它们的指南。

答案 7 :(得分:2)

在Visual Studio中进行编码时,它在某种程度上非常方便。

用例:假设我只使用几个类,例如来自命名空间SqlConnection的{​​{1}}。在正常过程中,我将导入* .cs文件顶部的System.Data命名空间,如下所示:

System.Data.SqlClient

现在看看我的intellisense。在键入代码编辑器时,它可以从众多类中大量涌入。我根本不打算使用一大堆课程:

enter image description here

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

using System.Data;

现在看看我的intellisense视图。它超级清晰,超级干净。

enter image description here

答案 8 :(得分:1)

我发现别名在单元测试中非常有用。在编写单元测试时,通常会将主题声明为

MyClass myClassUT;

myClassUT主题 U nder T \ test。但是如果你想用静态方法为静态类编写单元测试呢?然后你可以创建一个这样的别名:

using MyStaticClassUT = Namespace.MyStaticClass;

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

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

你永远不会忘记被测对象是什么。

答案 9 :(得分:1)

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

如果您在访问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#buff,但是别名命名空间似乎是&#34;最佳实践&#34;对我来说。这样你就可以知道你得到了什么,但仍然不必输入更多。

答案 10 :(得分:0)

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

例如:

library(caret)
library(neuralnet)

# Create the dataset
tt = data.frame(multiplier = rep(1:10, times = 10), multiplicand = rep(1:10, each = 10))
tt = cbind(tt, data.frame(product = tt$multiplier * tt$multiplicand))

# Splitting 
indexes = createDataPartition(tt$product,
                              times = 1,
                              p = 0.7,
                              list = FALSE)
tt.train = tt[indexes,]
tt.test = tt[-indexes,]

# Pre-process

preProc <- preProcess(tt, method = c('center', 'scale'))
tt.preProcessed <- predict(preProc, tt)
tt.preProcessed.train <- tt.preProcessed[indexes,]
tt.preProcessed.test <- tt.preProcessed[-indexes,]

# Train

train.control <- trainControl(method = "repeatedcv",
                              number = 10,
                              repeats = 3)

tune.grid <- expand.grid(layer1 = 8,
                         layer2 = 0,
                         layer3 = 0)

tt.cv <- train(product ~ .,
               data = tt.preProcessed.train,
               method = 'neuralnet',
               tuneGrid = tune.grid,
               trControl = train.control,
               linear.output = TRUE,
               algorithm = 'backprop',
               learningrate = 0.01,
               stepmax = 500000,
               lifesign = 'minimal',
               threshold = 0.01)

通过对指令的简单更改,您可以确定整个代码是在#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中工作。