C # -Namespace-Alias ​​- worum geht es?

95

Wo oder wann würde man Namespace-Aliasing wie verwenden

 using someOtherName =  System.Timers.Timer;

Es scheint mir, dass es dem Verständnis der Sprache nur mehr Verwirrung bringen würde.

Brad
quelle
6
Wie wäre es mit einem systemweiten using int = System.Int32C #? Nützlich, nicht wahr? Es ist die gleiche Verwendung, die anderswo genutzt werden kann.
Nawfal
@nawfal Ich glaube, Typ-Aliase sind nicht exportierbar. Das heißt, Sie können so etwas nicht definieren using int = System.Int32und an anderen Stellen als in der deklarierenden Datei verwenden. So dies intzu Int32alias kann entweder durch andere Mittel erreicht werden, oder ist eine besondere Sache im Compiler / runtime.
KFL
1
@KFL das stimmt, aber der Nutzen, den beide bieten, ist von gleicher Natur.
Nawfal
1
@nawfal Ihr Argument using int = System.Int32ist sowohl falsch als auch irreführend - es ist falsch, weil der intAlias ​​nicht so implementiert ist, wie Sie es beschrieben haben. Es ist irreführend, weil Sie implizieren, dass Typ-Aliase global verwendet werden können, genau wie intbei der Verwendung Int32.
KFL
2
@KFL Ich habe nicht beides impliziert. Ich habe gerade erklärt, warum es nützlich sein kann, einen benutzerdefinierten Namen für einen Typ zu haben.
Nawfal

Antworten:

151

Dies ist ein Typalias, kein Namespace-Alias. Es ist nützlich, zu unterscheiden - zum Beispiel gegen:

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

(ps: danke für die Wahl von Timer;-p)

Andernfalls müssen Sie, wenn Sie beide System.Windows.Forms.Timerund System.Timers.Timerdieselbe Datei verwenden, weiterhin die vollständigen Namen angeben (da Timerdies verwirrend sein kann).

Es spielt auch eine Rolle bei externAliasen für die Verwendung von Typen mit demselben vollqualifizierten Typnamen aus verschiedenen Assemblys - selten, aber nützlich, um unterstützt zu werden.


Eigentlich kann ich eine andere Verwendung sehen: Wenn Sie schnell auf einen Typ zugreifen möchten, aber keine reguläre verwenden möchten, usingweil Sie einige widersprüchliche Erweiterungsmethoden nicht importieren können ... etwas kompliziert, aber ... hier ist ein Beispiel ...

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) { }
    }
}
Marc Gravell
quelle
8
Es kann verwendet werden, um entweder Namespaces oder Typnamen zu aliasen.
Sean Bright
1
@ Sean: Ja, aber das gegebene Beispiel war ein Typ
Marc Gravell
@lupefiasco: bequem vom OP zu wählen System.Timers.Timer;-p
Marc Gravell
Ah, ich dachte, Sie beziehen sich auf das Konzept und nicht auf das spezifische Beispiel. Mea culpa.
Sean Bright
26

Ich benutze es, wenn ich mehrere Namespaces mit widersprüchlichen Sub-Namespaces und / oder Objektnamen habe. Sie könnten einfach so etwas wie [als Beispiel] tun:

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

...

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

Was sonst geschrieben werden müsste:

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

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

Es spart eine Menge Tipparbeit und kann verwendet werden, um das Lesen von Code zu vereinfachen.

BenAlabaster
quelle
17

Zusätzlich zu den genannten Beispielen können Typ-Aliase (anstelle von Namespace-Aliasen) nützlich sein, wenn wiederholt auf generische Typen verwiesen wird:

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

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

Gegen:

using FooDict = Dictionary<string, SomeClassWithALongName>;

FooDict foo = new FooDict();

private void DoStuff(FooDict dict) {}
Joel Mueller
quelle
8

Kürze.

Es gibt Nebeneffekte, um Klarheit zwischen Namespaces zu schaffen, die Typnamen gemeinsam haben, aber im Grunde ist es nur Zucker.

Annakata
quelle
Es zeigt deutlich, welches Symbol Sie verwenden. Es ist nicht nur Zucker, sondern ein bisschen ausführlich (wenn Sie keinen neuen Namen definieren möchten).
Earth Engine
7

Ich benutze es immer in solchen Situationen

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

wo Utilitysonst hätte ein anderer Kontext (wie MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility), aber ich erwarte / bevorzuge Utilityimmer auf diese eine bestimmte Klasse zu verweisen.

bdukes
quelle
6

Dies ist sehr nützlich, wenn Sie mehrere Klassen mit demselben Namen in mehreren enthaltenen Namespaces haben. Beispielsweise...

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

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

Sie können Aliase verwenden, um den Compiler glücklich zu machen und die Dinge für Sie und andere in Ihrem Team klarer zu machen:

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

/* ... */

CompanyA.Foo f = new CompanyA.Foo();
CompanyB.Foo x = new CompanyB.Foo();
Sean Bright
quelle
3

Wir haben Namespace-Aliase für alle unsere Namespaces definiert. Dies macht es sehr einfach zu erkennen, woher eine Klasse kommt, z.

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.

und

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

Wir haben einige Richtlinien definiert, wie die Aliase benannt werden müssen und jeder sie verwendet.

M4N
quelle
1
Finden Sie nicht, dass der Alias ​​oft mehr mit dem Kontext zu tun hat, in dem er verwendet wird, als mit dem physischen Standort des Objekts?
BenAlabaster
2

Ich finde die Aliase sehr nützlich beim Testen von Einheiten. Wenn Sie Komponententests schreiben, ist es üblich, das zu testende Subjekt als zu deklarieren

MyClass myClassUT;

wobei myClassUTdas Thema U nder T est. Aber was , wenn Sie für eine statische Klasse mit statischen Methoden zu schreiben Unit - Tests wollen? Dann können Sie einen Alias ​​wie folgt erstellen:

using MyStaticClassUT = Namespace.MyStaticClass;

Dann können Sie Ihre Unit-Tests folgendermaßen schreiben:

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

und Sie verlieren nie aus den Augen, was das zu testende Thema ist.

Charlie
quelle
2

In gewisser Weise ist es sehr praktisch beim Codieren in Visual Studio.

Anwendungsfall : Angenommen, ich muss nur wenige Klassen verwenden, z . B. SqlConnectionaus einem Namespace System.Data. Normalerweise importiere ich den System.Data.SqlClientNamespace oben in der * .cs-Datei wie folgt:

using System.Data;

Nun sieh dir meine Intelligenz an. Es gibt viele Klassen, aus denen Sie beim Eingeben im Code-Editor auswählen können. Ich werde überhaupt keine ganzen Klassen benutzen:

Geben Sie hier die Bildbeschreibung ein

Daher würde ich lieber einen Alias ​​oben in meiner * .cs-Datei verwenden und eine klare Intellisense-Ansicht erhalten:

using SqlDataCon = System.Data.SqlClient.SqlConnection

Schauen Sie sich jetzt meine Intellisense-Ansicht an. Es ist super klar und super sauber.

Geben Sie hier die Bildbeschreibung ein

RBT
quelle
1

Ein Grund, den ich kenne; Sie können kürzere Namen verwenden, wenn Sie Namenskollisionen von importierten Namespaces haben. Beispiel:

Wenn Sie beim Zugriff deklariert haben using System.Windows.Forms;und sich using System.Windows.Input;in derselben Datei ModifierKeysbefinden, stellen Sie möglicherweise fest, dass sich der Name ModifierKeyssowohl im System.Windows.Forms.Controlals auch im System.Windows.InputNamespace befindet. Wenn using Input = System.Windows.Input;Sie also deklarieren , können Sie System.Windows.Input.ModifierKeysüber Input.ModifierKeys.

Ich bin kein C # -Fan, aber Aliasing-Namespace scheint mir "Best Practice" zu sein. Auf diese Weise wissen Sie, was Sie bekommen und müssen immer noch nicht zu viel tippen.

Zv_oDD
quelle
1

Sie können sie verwenden, um einen Code sehr einfach zu ändern.

Beispielsweise:

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

Durch die einfache Änderung der Direktive können Sie entscheiden, ob Ihr gesamter Code in floatoder funktioniert double.

Ender Look
quelle