Alias ​​przestrzeni nazw C # - o co chodzi?

97

Gdzie i kiedy można by użyć aliasingu przestrzeni nazw, takiego jak

 using someOtherName =  System.Timers.Timer;

Wydaje mi się, że spowodowałoby to tylko większe zamieszanie w zrozumieniu języka.

Ćwiek
źródło
6
A co z całym systemem using int = System.Int32w C #? Przydatne, prawda? Jest to takie samo zastosowanie, które można wykorzystać gdzie indziej.
nawfal
@nawfal Uważam, że aliasów typów nie można eksportować. Oznacza to, że nie możesz zdefiniować czegoś podobnego using int = System.Int32i używać go w miejscach innych niż plik deklaracji. Więc to intdo Int32aliasu może być osiągnięte w inny sposób lub jest specjalną rzeczą w kompilatorze / środowisku wykonawczym.
KFL
1
@KFL to prawda, ale obie korzyści mają ten sam charakter.
nawfal
1
@nawfal twój argument using int = System.Int32jest zarówno błędny, jak i mylący - jest błędny, ponieważ intalias nie jest zaimplementowany w sposób, który opisałeś. Jest to mylące, ponieważ sugerujesz, że aliasy typów mogą być używane globalnie, tak jak intjest używane powyżej Int32.
KFL
2
@KFL i nie sugerowałem obu. Właśnie wyjaśniłem, dlaczego posiadanie niestandardowej nazwy dla typu może być przydatne.
nawfal

Odpowiedzi:

152

To jest alias typu, a nie alias przestrzeni nazw; warto ujednoznacznić - na przykład przed:

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

(ps: dzięki za wybór Timer;-p)

W przeciwnym razie, jeśli użyjesz obu System.Windows.Forms.Timeri System.Timers.Timerw tym samym pliku, będziesz musiał nadal podawać pełne nazwy (ponieważ Timermoże to być mylące).

Odgrywa również rolę z externaliasami do używania typów o tej samej w pełni kwalifikowanej nazwie typu z różnych zestawów - rzadko, ale przydatne do obsługiwania.


Właściwie widzę inne zastosowanie: gdy chcesz mieć szybki dostęp do typu, ale nie chcesz używać zwykłego, usingponieważ nie możesz zaimportować niektórych sprzecznych metod rozszerzeń ... trochę zawiłe, ale ... oto przykład ...

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
źródło
8
Może być używany do aliasowania przestrzeni nazw lub nazw typów.
Sean Bright
1
@Sean: tak, ale podany przykład dotyczy typu
Marc Gravell
@lupefiasco: wygodny do wyboru PO System.Timers.Timer;-p
Marc Gravell
Ach, myślałem, że odnosisz się do koncepcji, a nie do konkretnego przykładu. Mea culpa.
Sean Bright
26

Używam go, gdy mam wiele przestrzeni nazw z sprzecznymi przestrzeniami nazw podrzędnych i / lub nazwami obiektów, które można po prostu zrobić [jako przykład]:

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

...

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

Które inaczej musiałoby być napisane:

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

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

Oszczędza mnóstwo pisania i może być użyty do ułatwienia czytania kodu.

BenAlabaster
źródło
17

Oprócz wymienionych przykładów aliasy typów (zamiast aliasów przestrzeni nazw) mogą być przydatne, gdy wielokrotnie odwołujemy się do typów ogólnych:

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

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

Przeciw:

using FooDict = Dictionary<string, SomeClassWithALongName>;

FooDict foo = new FooDict();

private void DoStuff(FooDict dict) {}
Joel Mueller
źródło
8

Zwięzłość.

Istnieją dodatkowe korzyści, aby zapewnić przejrzystość między przestrzeniami nazw, które mają wspólne nazwy typów, ale zasadniczo to tylko cukier.

annakata
źródło
Wyraźnie pokazuje, jakiego symbolu używasz. To nie tylko cukier, ale trochę rozwlekły (jeśli nie chcesz definiować nowej nazwy).
Earth Engine
7

Zawsze go używam w takich sytuacjach

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

gdzie Utilityinaczej miałoby inny kontekst (jak MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility), ale oczekuję / wolę Utilityzawsze wskazywać na tę jedną konkretną klasę.

bdukes
źródło
6

Jest to bardzo przydatne, gdy masz wiele klas o tej samej nazwie w wielu dołączonych przestrzeniach nazw. Na przykład...

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

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

Możesz użyć aliasów, aby uszczęśliwić kompilator i uczynić rzeczy bardziej przejrzystymi dla siebie i innych członków zespołu:

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

/* ... */

CompanyA.Foo f = new CompanyA.Foo();
CompanyB.Foo x = new CompanyB.Foo();
Sean Bright
źródło
3

Zdefiniowaliśmy aliasy przestrzeni nazw dla wszystkich naszych przestrzeni nazw. Dzięki temu bardzo łatwo jest sprawdzić, skąd pochodzi klasa, np .:

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.

i

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

Zdefiniowaliśmy kilka wskazówek, jak należy nazywać aliasy i wszyscy ich używają.

M4N
źródło
1
Czy nie uważasz, że często alias ma więcej wspólnego z kontekstem, w którym jest używany, niż z fizyczną lokalizacją obiektu?
BenAlabaster
2

Uważam, że aliasy są bardzo przydatne w testach jednostkowych. Podczas pisania testów jednostkowych powszechną praktyką jest deklarowanie przedmiotu do testu jako

MyClass myClassUT;

bycie myClassUTprzedmiotem U nder T est. A co jeśli chcesz napisać testy jednostkowe dla klasy statycznej z metodami statycznymi? Następnie możesz utworzyć taki alias:

using MyStaticClassUT = Namespace.MyStaticClass;

Następnie możesz napisać swoje testy jednostkowe w następujący sposób:

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

i nigdy nie tracisz z oczu tego, czym jest testowany przedmiot.

Charlie
źródło
2

Z jednej strony jest to bardzo przydatne podczas kodowania w Visual Studio.

Przykład zastosowania : Powiedzmy, że mam użyć tylko kilku klas, np. SqlConnectionZ przestrzeni nazw System.Data. Normalnie zaimportuję System.Data.SqlClientprzestrzeń nazw na górze pliku * .cs, jak pokazano poniżej:

using System.Data;

Spójrz teraz na mój intelisens. Jest mocno rozpowszechniony z całą masą klas do wyboru podczas pisania w edytorze kodu. W ogóle nie zamierzam korzystać z całej masy zajęć:

wprowadź opis obrazu tutaj

Dlatego wolałbym raczej użyć aliasu na górze mojego pliku * .cs i uzyskać wyraźny widok IntelliSense:

using SqlDataCon = System.Data.SqlClient.SqlConnection

Spójrz teraz na mój intelisensowny widok. Jest super-przejrzysty i super-czysty.

wprowadź opis obrazu tutaj

RBT
źródło
1

Znam jeden powód; Pozwala używać krótszych nazw w przypadku kolizji nazw z importowanych przestrzeni nazw. Przykład:

Jeśli zadeklarowałeś using System.Windows.Forms;iw using System.Windows.Input; tym samym pliku, kiedy chcesz uzyskać dostęp ModifierKeys, może się okazać, że nazwa ModifierKeysznajduje się zarówno w przestrzeni nazw, jak System.Windows.Forms.Controli System.Windows.Input. Więc deklarując, using Input = System.Windows.Input;że możesz przejść System.Windows.Input.ModifierKeysprzezInput.ModifierKeys .

Nie jestem fanem C #, ale aliasowanie przestrzeni nazw wydaje mi się „najlepszą praktyką”. W ten sposób wiesz, co otrzymujesz i nadal nie musisz pisać zbyt wiele.

Zv_oDD
źródło
1

Możesz ich użyć do bardzo łatwej modyfikacji kodu.

Na przykład:

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

Dzięki prostej zmianie dyrektywy możesz zdecydować, czy cały kod działa w floatlub double.

Ender Look
źródło