C# – Strukturen vs. Klassen (Referenz vs. Werttyp) und wann was zu verwenden ist

C# – Strukturen vs. Klassen (Referenz vs. Werttyp) und wann was zu verwenden ist

Ich verwende niemals Strukturen - da habe ich es gesagt. Nicht, weil ich sie nicht mag oder der Meinung bin, dass sie keinen Nutzen haben, aber ich habe selten gesehen, dass andere Entwickler sie verwenden. Ich war auch Jahre in meiner Karriere, bevor ich sah, dass sie in einer Codebasis verwendet wurden. Hier spreche ich von Strukturen, die von Entwicklern definiert werden, nicht von denen, die in die Sprache eingebaut sind (DateTime, int usw.)

Um also etwas Licht ins Dunkel zu bringen, ob das, was ich tue, falsch oder richtig ist, wollte ich einen neuen Blick auf Strukturen werfen, was diesen Artikel ausgelöst hat.

Werttypen und Referenztypen

Es gibt einen grundlegenden Unterschied zwischen den beiden:Strukturen sind Werttypen und Klassen sind Referenztypen. Aber was bedeutet das?

Zunächst einmal gibt es einen großen Unterschied, wenn Sie Zuweisungen in Ihrem Code vornehmen. Referenztypzuweisungen kopieren die Referenz, während Wertzuweisungen den Wert kopieren. Das heißt, je mehr kopiert werden muss, desto größer sind die Operationen, die einem Werttyp zugewiesen werden müssen. Daher sind Referenztypen bei der Arbeit mit großen Strukturen billiger zuzuweisen, da sie nur einen Mauszeiger bewegen müssen.

Strukturen und Klassen werden auch speicherweise unterschiedlich zugewiesen, Werttypen gehen auf den Stack und Referenztypen auf den Heap (mit einem Zeiger darauf). Wenn Sie an der Speicherzuweisung in C# interessiert sind, würde ich diesen Artikel empfehlen. Für dieses Thema – Klassen vs. Struktur – ist der wichtige Teil:Zuweisungen und Freigaben von Werttypen sind normalerweise schneller als Zuweisungen und Freigaben von Referenztypen

Der größte Unterschied der beiden (meiner Meinung nach) besteht darin, dass Werttypen per Kopie und Referenztypen per Referenz weitergegeben werden. Dies kann zu unerwünschten Ergebnissen führen, wenn Sie nicht wissen, wie Strukturen funktionieren. Unten habe ich ein kleines Beispiel gemacht:

static void Main(string[] args)
{
    Struct1 struct1 = new Struct1();
    struct1.I = 1;
    SetITo2(struct1);
    Console.WriteLine(struct1.I); //still 1
    Console.ReadKey();
}

public static void SetITo2(Struct1 struct1)
{
    struct1.I = 2;
}

public struct Struct1
{
    public int I { get; set; }
}

Oben deklariere ich die Variable struct1 mit einer Eigenschaft I was eine ganze Zahl ist. Dann weise ich I den Wert 1 zu . Der Typ struct1 ist ein Werttyp. Ich rufe dann eine Methode auf, die dieser Variablen 2 zuweist. Dies ändert jedoch nicht den Wert von i Variable in der Main-Methode. Dies liegt an der Weitergabe an SetTo2() Methode als Kopie und nicht als Referenz. Wir können dies umgehen, indem wir es als Referenz übergeben (mit dem ref Schlüsselwort):

static void Main(string[] args)
{
    Struct1 struct1 = new Struct1();
    struct1.I = 1;
    SetITo2(ref struct1);
    Console.WriteLine(struct1.I); //now 2
    Console.ReadKey();
}

public static void SetITo2(ref Struct1 struct1)
{
    struct1.I = 2;
}

Eine andere Möglichkeit, dies zu erreichen, wäre, unsere Variable i zu umschließen in einem class (Referenztyp) statt struct :

static void Main(string[] args)
{
    Class1 class1 = new Class1();
    class1.I = 1;
    SetITo2(class1);
    Console.WriteLine(class1.I); //now 2
    Console.ReadKey();
}

public static void SetITo2(Class1 class1)
{
    class1.I = 2;
}

public class Class1
{
    public int I { get; set; }
}

Nicht zu wissen, wie Typen weitergegeben werden (durch Verweis oder durch Kopieren), kann zu einem merkwürdigen Verhalten führen. Ich denke, dies ist der wichtigste Unterschied, den man über Wert- und Referenztypen wissen sollte. In meinen Beispielen

Ein weiterer Hinweis ist, dass Strukturen idealerweise auch unveränderlich sein sollten. Das erste der obigen Beispiele hätte auch vermieden werden können, wenn die Struktur unveränderlich gewesen wäre (wenn Sie den Wert nur einmal hätten setzen können).

Strukturen haben mehrere Einschränkungen, die Klassen nicht haben. Strukturen können nicht:

  • Von anderen Strukturen oder Klassen ableiten
  • Definieren Sie explizit einen parameterlosen Standardkonstruktor

Sie können auch einen Werttyp in einen Werttyp umwandeln und wieder zurück. Das nennt man Boxen und Unboxen. Ein Beispiel dafür wäre:

int i = 0;
Object k = i;

Oben unser Werttyp i wird in den Referenztyp k eingerahmt. Das heißt, es ist jetzt ein Referenztyp und kein Werttyp. Ich habe hier einen ausführlicheren Artikel über Boxen und Unboxing geschrieben.

Kurz gesagt

Normalerweise möchten Sie Klassen verwenden. Aber es gibt ein paar Ausnahmen:

  • Es ist unveränderlich
  • Es ist klein (<16 Bytes)
  • Es muss nicht oft ein- und ausgepackt werden.

Das ist es! Ich hoffe, Ihnen hat mein Beitrag über Strukturen vs. Klassen gefallen. Sag mir deine Meinung in den Kommentaren!

Ressourcen

Für diesen Artikel habe ich die folgenden Ressourcen verwendet:

  • Zwischen Klasse und Struktur wählen
  • Was ist der Unterschied zwischen Struktur und Klasse in .NET?
  • Wann verwendet man eine Struktur anstelle einer Klasse?