Strukturen

Strukturen

# Eine Struktur deklarieren

public struct Vector 
{
    public int X;
    public int Y;
    public int Z;
}

public struct Point
{
    public decimal x, y;
    
    public Point(decimal pointX, decimal pointY)
    {
        x = pointX;
        y = pointY;
    }
}

  • `struct`-Instanzfelder können über einen parametrisierten Konstruktor oder einzeln nach der `struct`-Konstruktion gesetzt werden.
  • Private Member können nur vom Konstruktor initialisiert werden.
  • `struct` definiert einen versiegelten Typ, der implizit von System.ValueType erbt.
  • Strukturen können nicht von anderen Typen erben, aber sie können Schnittstellen implementieren.
  • Strukturen werden bei der Zuweisung kopiert, was bedeutet, dass alle Daten in die neue Instanz kopiert werden und Änderungen an einer von ihnen nicht von der anderen übernommen werden.
  • Eine Struktur kann nicht 'null' sein, obwohl sie **als nullable-Typ verwendet werden kann**:
    Vector v1 = null; //illegal
    Vector? v2 = null; //OK
    Nullable<Vector> v3 = null // OK
    
    
  • Strukturen können mit oder ohne Verwendung des `new`-Operators instanziiert werden.
    //Both of these are acceptable
    Vector v1 = new Vector();
    v1.X = 1;
    v1.Y = 2;
    v1.Z = 3;
    
    Vector v2;
    v2.X = 1;
    v2.Y = 2;
    v2.Z = 3;
    
    

    Aber der new Operator muss verwendet werden, um einen Initialisierer zu verwenden:

    Vector v1 = new MyStruct { X=1, Y=2, Z=3 }; // OK
    Vector v2 { X=1, Y=2, Z=3 }; // illegal
    
    
  • Eine Struktur kann alles deklarieren, was eine Klasse deklarieren kann, mit einigen Ausnahmen:

    • Eine Struktur kann keinen parameterlosen Konstruktor deklarieren. struct Instanzfelder können über einen parametrisierten Konstruktor oder einzeln hinter struct gesetzt werden Konstruktion. Private Member können nur vom Konstruktor initialisiert werden.
    • Eine Struktur kann Mitglieder nicht als geschützt deklarieren, da sie implizit versiegelt ist.
    • Strukturfelder können nur initialisiert werden, wenn sie konstant oder statisch sind.

    # Struct-Verwendung

    Mit Konstruktor:

    Vector v1 = new Vector();
    v1.X = 1;
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    // Output X=1,Y=2,Z=3
    
    Vector v1 = new Vector();
    //v1.X is not assigned
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    // Output X=0,Y=2,Z=3
    
    Point point1 = new Point();
    point1.x = 0.5;
    point1.y = 0.6;
    
    Point point2 = new Point(0.5, 0.6);
    
    

    Ohne Konstruktor:

    Vector v1;
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    //Output ERROR "Use of possibly unassigned field 'X'
    
    Vector v1;
    v1.X = 1;
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    // Output X=1,Y=2,Z=3
    
    Point point3;
    point3.x = 0.5;
    point3.y = 0.6;
    
    

    Wenn wir eine Struktur mit ihrem Konstruktor verwenden, werden wir keine Probleme mit nicht zugewiesenen Feldern haben (jedes nicht zugewiesene Feld hat einen Nullwert).

    Im Gegensatz zu Klassen muss eine Struktur nicht konstruiert werden, d. h. es besteht keine Notwendigkeit, das Schlüsselwort new zu verwenden, es sei denn, Sie müssen einen der Konstruktoren aufrufen. Eine Struktur erfordert das Schlüsselwort new nicht, da sie ein Werttyp ist und daher nicht null sein kann.

    # Struct-implementierende Schnittstelle

    public interface IShape
    {
        decimal Area();
    }
    
    public struct Rectangle : IShape
    {
        public decimal Length { get; set; }
        public decimal Width { get; set; }
    
        public decimal Area()
        {
            return Length * Width;
        }
    }
    
    

    # Strukturen werden bei Zuweisung kopiert

    Da Strukturen Werttypen sind, werden alle Daten kopiert bei der Zuweisung, und jede Änderung an der neuen Kopie ändert nicht die Daten für die ursprüngliche Kopie. Das folgende Code-Snippet zeigt diesen p1 wird kopiert bis p2 und Änderungen, die am p1 vorgenommen wurden wirkt sich nicht auf p2 aus Beispiel.

    var p1 = new Point {
        x = 1,
        y = 2
    };
    
    Console.WriteLine($"{p1.x} {p1.y}"); // 1 2
    
    var p2 = p1;
    Console.WriteLine($"{p2.x} {p2.y}"); // Same output: 1 2
    
    p1.x = 3;
    Console.WriteLine($"{p1.x} {p1.y}"); // 3 2
    Console.WriteLine($"{p2.x} {p2.y}"); // p2 remain the same: 1 2
    
    

    # Bemerkungen

    Im Gegensatz zu Klassen ist ein struct ist ein Werttyp und wird standardmäßig auf dem lokalen Stack und nicht auf dem verwalteten Heap erstellt . Dies bedeutet, dass sobald der spezifische Stack den Gültigkeitsbereich verlässt, der struct wird freigegeben. Enthaltene Referenztypen von freigegebenem struct s werden ebenfalls ausgeräumt, sobald der GC feststellt, dass auf sie nicht mehr durch struct verwiesen wird .

    struct s können nicht erben und können keine Basis für die Vererbung sein, sie sind implizit versiegelt und können auch nicht protected enthalten Mitglieder. Allerdings ein struct kann eine Schnittstelle implementieren, wie es Klassen tun.