Typ-Aliase definieren

73

Eine Funktion von Pascal, die ich sehr nützlich fand, war die Möglichkeit, einen Datentyp zu benennen, z

type
 person: record
             name: string;
             age: int;
         end;

var
 me: person;
 you: person;

etc

Können Sie etwas Ähnliches in C # tun? Ich möchte in der Lage sein, so etwas zu tun

using complexList = List<Tuple<int,string,int>>;

complexList peopleList;
anotherList otherList;

Wenn ich also die Definition des Datentyps ändern muss, kann ich dies an einem Ort tun.

Unterstützt C # einen Weg, dies zu erreichen?

hochmütig
quelle
9
Ein " usingAlias" in c # ist nur pro Datei
Marc Gravell
Hier ist eine weitere Frage im Zusammenhang damit: stackoverflow.com/questions/161477/…
Candide

Antworten:

62

Es ist nicht genau das, was Sie in Pascal tun, aber Sie können die using-directive verwenden. Schauen Sie sich hier an, wie man es benutzt

Beispiel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyList = Dummy2.CompleXList;

namespace Dummy2
{
    public class Person 
    {
    }

    public class CompleXList : List<Person> 
    { 
    }


    class Program
    {
        static void Main(string[] args)
        {
            MyList l1 = new MyList();
        }
    }
}
Mithrandir
quelle
27
kleiner Punkt: usingAm Anfang einer Datei stehen Direktiven , keine Anweisungen . Die "using-Anweisung" ist die Sache, um die es geht IDisposable. Dies ist insbesondere ein "Verwendungsalias".
Marc Gravell
2
Bemerkenswert: Auch wenn Sie nur die Klasse "MyList" nennen, ist die using-Direktive natürlich nicht mehr erforderlich (und das löst auch das ursprüngliche Problem).
BrainSlugs83
Der Link verweist auf eine ältere Dokumentationsseite. Während noch aktiv und genau (und mit dem folgenden Link), ist hier der Link zur neueren Seite, falls die alte Seite entfernt wird. docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
MadCityDev
2
Funktioniert das irgendwie für benannte Tupel? Ich kann es nicht zum Laufen bringen. Was ich versuche ist folgendes : using MyType = (TypeA a, TypeB b);. Ich denke, ich könnte unbenannte Tupel verwenden und es würde funktionieren, aber ich möchte wirklich die Namen und nicht Item1, Item2. :(
user2173353
83

Ja es ist möglich. Du kannst schreiben:

using System;
using System.Collections.Generic;

namespace ConsoleApplication12
{
    using MyAlias = List<Tuple<int, string, int>>;
}

oder, wenn außerhalb des Namespace deklariert:

using System;
using System.Collections.Generic;

using MyAlias = System.Collections.Generic.List<System.Tuple<int, string, int>>;

namespace ConsoleApplication12
{
}

Verwenden Sie es dann als Typ:

MyAlias test = new MyAlias();
ken2k
quelle
1
hast du das versucht es wird nicht kompiliert (vorausgesetzt, es List<T>ist das typische); Für einen usingAlias ​​muss immer der vollständige Namespace angegeben werden.
Marc Gravell
1
@MarcGravell Natürlich habe ich es getestet, es kompiliert definitiv und funktioniert gut.
Ken2k
2
@Jodrell Ich sehe sehr selten usingAnweisungen in der namespace, hauptsächlich, weil die meisten Tools sie dort nicht platzieren.
Marc Gravell
6
@ ken2k können Sie MyAlias ​​exportieren und in anderen Quelldateien verwenden? Wie machst du das?
gen
2
Warum ist dies nicht die akzeptierte Antwort? Dies bietet tatsächlich die Lösung für die Frage
AustinWBryan
19

Sie können einen Typ erstellen:

class ComplexList : List<Tuple<int,string,int>> { }

Dies ist nicht unbedingt dasselbe wie ein Alias, aber in den meisten Fällen sollten Sie keine Unterschiede feststellen.

Serge Wautier
quelle
@ Serge-appTranslator, wenn es nicht das gleiche wie meine Antwort war, aber 2 Minuten später.
Jodrell
2
@ Jodrell: Autsch! Ich denke, wir haben es zur gleichen Zeit getippt. Sie haben gerade die Rennbedingung gewonnen. Übrigens, Ihre Antwort ist ausgezeichnet: Ich stimme zu ;-)
Serge Wautier
Ich habe noch nie daran gedacht, obwohl es so offensichtlich aussieht, wenn ich es mir ansehe! Vielen Dank, dass Sie mich auf diese Idee aufmerksam gemacht haben! :)
Patrik Forsberg
5
Dies funktioniert jedoch nicht, wenn der Typ versiegelt ist (z. B. Sie versuchen, "Alias" KeyValuePair<K,V>)
Liam Dawson
1
Dies kann auch zu Gleichheitsprüfungen aufgrund von Unterklassen führen. Unterklasse! = Aliasing.
Ryan The Leach
16

Was ist mit Vererbung?

class ComplexList : List<Tuple<int, string, int>> {}

var complexList = new ComplexList();

Dies scheint ein ähnliches Konzept zu sein, aber es gibt kein direktes Äquivalent eines typbasierten Alias ​​in C #, sondern nur Namespace-Aliase .

Wenn Sie vermeiden möchten, dass Typnamen in Ihrem Code zusammenstoßen, ist Namespace-Aliasing der richtige Weg.

Wenn Sie einen neuen Typ erstellen möchten, der eine Instanz eines anderen Typs ist, ist die Vererbung eine Option.

Jodrell
quelle
5
Außer die Verwendung der Vererbung schlägt in allen Fällen fehl, in denen der Typ, auf den sich der Alias ​​bezieht, versiegelt ist.
Allen Clark Copeland Jr.
7
Wenn Sie dies jedoch so tun und eine void Foo(ComplexList a)Methode deklarieren , ist das Aufrufen als Foo(new List<Tuple<int,string,int>>();ein Typfehler, obwohl die Typen isomorph sind.
Cemper93
1
Vererbung ist weit entfernt von einem Vorteil, es sei denn, Sie möchten tatsächlich die Funktionen der Unterklasse. In jedem anderen Fall führt dies zu Overhead, Indirektion, Langsamkeit und Unzuverlässigkeit. Sie können die Klasse außerdem nicht mit Bibliotheken verwenden, die auf einem bestimmten Typ basieren. Tatsächlich erfordert die Bedeutung des Wortes "Alias", dass der Typ immer noch der gleiche ist. Vererbung ist mit anderen Worten KEIN Aliasing. Mit Aliasing können Sie das Objekt an eine Methode übergeben, die den Alias ​​ohne Casting nicht gemeinsam genutzt hat.
Zane Claes
@ZaneClaes, ich habe den Teil "(With Benefits.)" Aus meiner Antwort entfernt. Ich bin nicht der Meinung, dass die Bedeutung des Wortes Alias ​​im Allgemeinen eine spezifische Bedeutung für Typsysteme hat. Die C # -Vererbung ist jedoch kein starkes Äquivalent für einen Pascal-Alias, aber es gibt kein starkes Äquivalent. Im Nachhinein würde mich die akzeptierte Antwort mehr anziehen.
Jodrell
1
@Jodrell gemäß der Wörterbuchdefinition von "Alias" in "Computing": "Ein alternativer Name oder eine alternative Bezeichnung, die sich auf [...] ein Element bezieht und zum Auffinden verwendet werden kann." Per Definition kann eine Unterklasse daher kein Alias ​​sein, da sie nicht auf die Oberklasse verweist oder diese lokalisiert. Es ist eine völlig neue Einheit. Auf Compilerebene sind die beiden keine äquivalenten oder alternativen Versionen voneinander.
Zane Claes
6

Aus der in der ersten Frage gezeigten Syntax geht hervor, dass Sie wirklich nur fragen, wie eine Klasse in C # erstellt wird und nicht, wie ein Typ aliasisiert wird.

Wenn Sie einen einfacheren Namen eingeben möchten als List<Tuple<int,string,int>>und "global" (dh nicht pro Datei), würde ich eine neue Klasse erstellen, die diese Klasse erbt und keine zusätzlichen Mitglieder deklariert. So was:

public class MyTrinaryTupleList: List<Tuple<int,string,int>> { }

Dies gibt einen einzigen Verwaltungsstandort und erfordert keine zusätzlichen using-Anweisungen.

Ich würde jedoch auch noch einen Schritt weiter gehen und wagen, dass Sie wahrscheinlich kein Tupel wollen, sondern eine andere Klasse, wie zum Beispiel:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public int FavoriteNumber { get; set; }

    public Person() { }

    public Person(string name, int age, int favoriteNumber) 
    { 
        this.Name = name; 
        this.Age = age; 
        this.FavoriteNumber = favoriteNumber; 
    }
}

Und dann können Sie für Ihren Listentyp Folgendes tun:

public class PersonList: List<Person> { }

Wenn Sie andere listenspezifische Hilfseigenschaften oder -methoden benötigen, können Sie diese auch der PersonList-Klasse hinzufügen.

BrainSlugs83
quelle
4

Ja, Sie können dies tun, müssen jedoch die vollständigen Typen angeben, dh die Definition lautet:

using ComplexList = System.Collections.Generic.List<System.Tuple<int,string,int>>;

Dies wird pro Datei angegeben, ähnlich wie bei den using-Anweisungen für Namespaces.

nitpick: Herkömmlicherweise ist ein Typ in .NET PascalCased.

flq
quelle
"Vollständige Typen" sind nicht erforderlich. Wenn andere using(wie using System.Collections.Generic;vorhanden), sind "vollständige Typen" nicht erforderlich.
Ken2k
2
@ ken2k falsch; Ein usingAlias ​​erfordert immer eine explizite Namespace-Qualifizierung, selbst wenn die vorhandenen usingAnweisungen ihn in den Geltungsbereich bringen würden. Bedeutung: using var list = List<int>;ist nicht gültig, auch nachusing System.Collections.Generic;
Marc Gravell
1
Es ist nicht erforderlich, wenn der Alias ​​tatsächlich im Bereich eines Namespace definiert ist.
Ken2k
1

Nur eine einfache Verwendung würde reichen:

using Foo = System.UInt16;

public class Test {
  public Foo Bar { get;set; }
}
juFo
quelle