Anonyme Typen

Anonyme Typen stellen eine praktische Möglichkeit dar, einen Satz schreibgeschützter Eigenschaften in einem Objekt zu kapseln, ohne zuerst explizit einen Typ definieren zu müssen. Der Typname wird vom Compiler generiert und ist auf Quellcodeebene nicht verfügbar. Der Typ der einzelnen Eigenschaften wird vom Compiler abgeleitet.

Sie erstellen anonyme Typen mit dem new-Operator und einem Objektinitialisierer. Informationen über Objektinitialisierer finden Sie unterObjekt- und Auflistungsinitialisierer.

Das folgende Beispiel veranschaulicht einen anonymen Typ, der mit den beiden Eigenschaften Amount und Message initialisiert wird.

var v = new { Amount = 108, Message = "Hello" };

// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);

Anonyme Typen werden normalerweise in der select-Klausel eines Abfrageausdrucks verwendet, um von jedem Objekt in der Quellsequenz eine Teilmenge der Eigenschaften zurückzugeben. Weitere Informationen zu Abfragen finden Sie unter LINQ in C#.

Anonyme Typen enthalten mindestens eine schreibgeschützte Eigenschaft. Andere Arten von Klassenmembern wie Methoden oder Ereignisse sind ungültig. Der Ausdruck, der zum Initialisieren einer Eigenschaft verwendet wird, kann weder null noch eine anonyme Funktion oder ein Zeigertyp sein.

Das gängigste Szenario ist die Initialisierung eines anonymen Typs mit den Eigenschaften eines anderen Typs. Nehmen Sie im folgenden Beispiel an, dass eine Klasse mit dem Namen Product vorhanden ist. Die Product-Klasse enthält die Eigenschaften Color und Price sowie weitere Eigenschaften, die für Sie nicht relevant sind. Die Variable products ist eine Auflistung von Product-Objekten. Die Deklaration eines anonymen Typs beginnt mit dem Schlüsselwort new. Die Deklaration initialisiert einen neuen Typ, der nur zwei Eigenschaften von Product verwendet. Durch Verwendung anonymer Typen werden in der Abfrage weniger Daten zurückgegeben.

Wenn Sie im anonymen Typ keine Membernamen angeben, gibt der Compiler den Membern des anonymen Typs den Namen der Eigenschaft, mit der sie initialisiert werden. Sie geben einen Namen für eine Eigenschaft an, die mit einem Ausdruck initialisiert wird, wie im vorherigen Beispiel dargestellt. Im folgenden Beispiel lauten die Namen der Eigenschaften des anonymen Typs Color und Price.

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

Tipp

Sie können die .NET-Stilregel IDE0037 verwenden, um festzulegen, ob abgeleitete oder explizite Membernamen bevorzugt werden.

Es ist auch möglich, ein Feld nach Objekten eines anderen Typs zu definieren: nach Klasse, Struktur oder einem anderen anonymen Typ. Dazu wird die Variable verwendet, die dieses Objekt enthält, wie im folgenden Beispiel, in dem zwei anonyme Typen mithilfe bereits instanziierter benutzerdefinierter Typen erstellt werden. In beiden Fällen ist das Feld product vom anonymen Typ shipment und shipmentWithBonus vom Typ Product, wobei die Standardwerte jedes Felds enthalten sind. Das Feld bonus weist einen vom Compiler erstellten anonymen Typ auf.

var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };

Wenn Sie einen anonymen Typ zum Initialisieren einer Variablen verwenden, deklarieren Sie die Variable normalerweise mithilfe von var als implizit typisierte lokale Variable. Der Typname kann in der Variablendeklaration nicht angegeben werden, da nur der Compiler über Zugriff auf den zugrunde liegenden Namen des anonymen Typs verfügt. Weitere Informationen zu var finden Sie unter Implizit typisierte lokale Variablen.

Sie können ein Array anonym typisierter Elemente erstellen, indem Sie eine implizit typisierte lokale Variable und ein implizit typisiertes Array kombinieren, wie im folgenden Beispiel veranschaulicht.

var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};

Anonyme Typen sind class, die direkt vom object abgleitet werden und in keinen anderen Typ als ein object umgewandelt werden können. Der Compiler gibt für jeden anonymen Typ einen Namen an, Ihre Anwendung kann jedoch nicht darauf zugreifen. Aus der Perspektive der Common Language Runtime unterscheidet sich ein anonymer Typ nicht von anderen Verweistypen.

Wenn zwei oder mehr anonyme Objektinitialisierer in einer Assembly eine Sequenz von Eigenschaften angeben, die die gleiche Reihenfolge und die gleichen Namen und Typen aufweisen, behandelt der Compiler die Objekte als Instanzen desselben Typs. Sie erhalten die gleichen vom Compiler generierten Typinformationen.

Anonyme Typen unterstützen eine nicht destruktive Mutation in Form von with-Ausdrücken. So können Sie eine neue Instanz eines anonymen Typs erstellen, in der mindestens eine Eigenschaft neue Werte aufweist:

var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);

Sie können ein Feld, eine Eigenschaft, ein Ereignis oder den Rückgabetyp einer Methode nicht mit einem anonymen Typ deklarieren. Auch können Sie einen formalen Parameter einer Methode, einer Eigenschaft, eines Konstruktors oder eines Indexers nicht als anonymen Typ deklarieren. Um einen anonymen Typ oder eine Auflistung mit anonymen Typen als Argument einer Methode zu übergeben, können Sie den Parameter als object-Typ deklarieren. Die Verwendung von object für anonyme Typen verfehlt jedoch den Zweck der starken Typisierung. Wenn Sie Abfrageergebnisse speichern oder außerhalb der Methodengrenze übergeben müssen, könnten Sie statt eines anonymen Typs eine Struktur oder Klasse mit einem gewöhnlichen Namen verwenden.

Da die Methoden Equals und GetHashCode von anonymen Typen anhand der Methoden Equals und GetHashCode der Eigenschaften definiert werden, sind zwei Instanzen eines anonymen Typs nur gleich, wenn alle Eigenschaften gleich sind.

Hinweis

Die Zugriffsebene eines anonymen Typs ist internal, daher sind zwei anonyme Typen, die in verschiedenen Assemblys definiert sind, nicht vom gleichen Typ. Daher können Instanzen anonymer Typen nicht gleich sein, wenn sie in verschiedenen Assemblys definiert sind, auch wenn alle ihre Eigenschaften gleich sind.

Anonyme Typen überschreiben die ToString-Methode und verketten den Namen und die ToString-Ausgabe jeder Eigenschaft, die in geschweiften Klammern steht.

var v = new { Title = "Hello", Age = 24 };

Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"