Strukturen

Eine Struktur ist ein Werttyp. Wenn eine Struktur erstellt wird, enthält die Variable, der die Struktur zugewiesen wird, die eigentlichen Daten der Struktur. Wenn die Struktur einer neuen Variable zugewiesen wird, werden diese kopiert. Die neue Variable und die ursprüngliche Variable enthalten daher zwei separate Kopien der gleichen Daten. Änderungen an einer Kopie wirken sich nicht auf die andere Kopie aus.

Werttypvariablen enthalten die zugehörigen Werte direkt, d. h., der Speicher wird inline in dem Kontext belegt, in dem die Variable deklariert ist. Für Werttypvariablen erfolgt keine getrennte Heapzuordnung oder ein Mehraufwand für die Garbage Collection.

Zwei Kategorien von Werttypen sind verfügbar: struct und enum.

Die integrierten numerischen Typen sind Strukturen und verfügen über Eigenschaften und Methoden, auf die Sie zugreifen können:

// Static method on type Byte.  
byte b = Byte.MaxValue;

Sie deklarieren diese jedoch und weisen ihnen Werte zu, als wären es einfache, nicht aggregierte Typen:

byte num = 0xA;  
int i = 5;  
char c = 'Z';

Werttypen sind versiegelt (sealed). Dies bedeutet z.B., dass Sie keinen Typ von @System.Int32 ableiten können und dass eine Struktur nicht von einer benutzerdefinierten Klasse oder Struktur erben kann, weil eine Struktur nur von @System.ValueType erben kann. Eine Struktur kann jedoch eine oder mehrere Schnittstellen implementieren. Sie können einen Strukturtyp in einen Schnittstellentyp umwandeln. Dadurch wird ein Boxing-Vorgang gestartet, mit dem die Struktur von einem Referenztypobjekt im verwalteten Heap umschlossen wird. Boxing-Vorgänge werden auch ausgeführt, wenn Sie einen Werttyp an eine Methode übergeben, die @System.Object als Eingabeparameter akzeptiert. Weitere Informationen finden Sie unter Boxing und Unboxing.

Sie können das struct-Schlüsselwort verwenden, um eigene benutzerdefinierte Werttypen zu erstellen. In der Regel wird eine Struktur als Container für einen kleinen Satz verwandter Variablen verwendet, wie im folgenden Beispiel dargestellt:

public struct CoOrds
{
    public int x, y;

    public CoOrds(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}

Weitere Informationen über Werttypen im .NET Framework finden Sie unter Allgemeines Typsystem.

Strukturen teilen sich einen großen Teil der Syntax mit Klassen, obwohl Strukturen eingeschränkter als Klassen sind:

  • Innerhalb einer Strukturdeklaration können Felder nicht initialisiert werden, außer Sie werden als const oder static deklariert.

  • Eine Struktur kann keinen Standardkonstruktor (ein Konstruktor ohne Parameter) oder Finalizer deklarieren.

  • Strukturen werden bei Zuweisung kopiert. Wenn eine Struktur einer neuen Variable zugewiesen wird, werden alle Daten kopiert, und jede Änderung an der neuen Kopie ändert nicht die Daten für das Original. Es ist wichtig, sich das zu merken, wenn Sie mit Auflistungen von Wertetypen wie Dictionary<string, myStruct> arbeiten.

  • Strukturen sind Werttypen, und Klassen sind Verweistypen.

  • Strukturen können im Gegensatz zu Klassen ohne den Operator new instanziiert werden.

  • Strukturen können Konstruktoren deklarieren, die Parameter besitzen.

  • Eine Struktur kann nicht von einer anderen Struktur oder Klasse erben, und sie kann auch nicht die Basis einer Klasse sein. Alle Strukturen erben direkt von @System.ValueType, das von @System.Object erbt.

  • Eine Struktur kann Schnittstellen implementieren.

Literalwerte

In C# erhalten Literalwerte einen Typ vom Compiler. Sie können festlegen, wie ein numerisches Literal eingegeben werden soll, indem Sie am Ende der Zahl einen Buchstaben anfügen. Um z. B. anzugeben, dass der Wert 4.56 als Gleitkommazahl behandelt werden soll, fügen Sie nach der Zahl 4.56f ein "f" oder "F" an: Wenn kein Buchstabe angefügt wird, leitet der Compiler den double-Typ für das Literal ab. Weitere Informationen darüber, welche Typen mit Buchstabensuffixen angegeben werden können, finden Sie auf den Referenzseiten für einzelne Typen unter Werttypen.

Da Literale typisiert sind und alle Typen letztlich von @System.Object abgeleitet werden, können Sie Code der folgenden Art erstellen und kompilieren:

string s = "The answer is " + 5.ToString();
// Outputs: "The answer is 5"
Console.WriteLine(s);

Type type = 12345.GetType();
// Outputs: "System.Int32"
Console.WriteLine(type);

var x = 123_456;
string s2 = "I can use an underscore as a digit separator: " + x;
// Outputs: "I can use an underscore as a digit separator: 
Console.WriteLine(s2);

var b = 0b1010_1011_1100_1110_1111;
string s3 = "I can specify bit patterns: " + b.ToString();
// Outputs: "I can specify bit patterns: 703727
Console.WriteLine(s3);

Die letzten beiden Beispiele veranschaulichen die Sprachfunktionen, die in C# 7.0 eingeführt wurden. Mit dem Ersten können Sie ein Unterstrichzeichen als eine Zeichentrennlinie in numerischen Literalen verwenden. Sie können es beliebig zwischen Zahlen setzen, um die Lesbarkeit zu verbessern. Es hat keine Auswirkung auf den Wert.

Im zweiten Beispiel werden binäre Literale veranschaulicht, mit denen Sie ein Bitmuster direkt angeben können, anstatt Hexadezimalnotation zu verwenden.

Auf NULL festlegbare Typen

Gewöhnliche Werttypen können den Wert NULL nicht aufweisen. Sie können jedoch auf NULL festlegbare Werttypen erstellen, indem Sie ein ? nach dem Typ anfügen. Zum Beispiel ist int? ein int-Typ, der auch den Wert NULL haben kann. Im CTS sind Typen, die NULL-Werte zulassen, Instanzen vom generischen Strukturtyp @System.Nullable%601. Typen, die NULL-Werte zulassen, sind besonders hilfreich, wenn Sie Daten an und aus Datenbanken übergeben, in denen die numerischen Werte NULL sein können. Weitere Informationen finden Sie unter Typen, die NULL-Werte zulassen (C#-Programmierhandbuch).

Siehe auch

Klassen

Grundlegende Typen