Freigeben über


C#-Klassen

Tipp

Neu bei der Entwicklung von Software? Beginnen Sie zuerst mit den Lernprogrammen " Erste Schritte ". Sie werden auf Klassen stoßen, sobald Sie Objekte mit Verhalten und Zustand modellieren müssen.

Haben Sie Erfahrung in einer anderen Sprache? C#-Klassen ähneln Klassen in Java oder C++. Überspringen Sie den Abschnitt "Objektinitialisierer " für C#-spezifische Muster, und siehe Datensätze für eine datenorientierte Alternative.

Eine Klasse ist ein Verweistyp, der einen Blueprint für Objekte definiert. Wenn Sie eine Variable eines Klassentyps erstellen, enthält die Variable einen Verweis auf ein Objekt im verwalteten Heap. Die Variable enthält die Objektdaten nicht selbst. Durch das Zuweisen einer Klassenvariable zu einer anderen Variablen wird der Verweis kopiert, sodass beide Variablen auf dasselbe Objekt verweisen. Klassen sind die am häufigsten verwendete Methode zum Definieren von benutzerdefinierten Typen in C#. Verwenden Sie sie, wenn Sie komplexes Verhalten, Vererbung oder gemeinsame Identität zwischen Verweisen benötigen.

Wann man Klassen verwenden sollte

Verwenden Sie eine Klasse in folgenden Fällen:

  • Der Typ weist ein komplexes Verhalten auf oder verwaltet den veränderbaren Zustand.
  • Sie benötigen die Vererbung, um eine Basisklasse mit abgeleiteten Spezialisierungen zu erstellen oder einen abgeleiteten Typ zu erstellen, der eine vorhandene Klasse erweitert.
  • Instanzen repräsentieren eine gemeinsame Identität, nicht Objekte, die zufällig gleiche Werte aufweisen. Zwei Verweise auf dasselbe Objekt sollten synchronisiert bleiben.
  • Der Typ ist von großer Größe oder Langlebigkeit und profitiert von Heap-Allocation und Referenzsemantik.

Deklarieren einer Klasse

Definieren Sie eine Klasse mit dem class Schlüsselwort gefolgt vom Typnamen. Ein optionaler Zugriffsmodifizierer steuert die Sichtbarkeit. Der Standardwert lautet internal. Geben Sie public an, um Aufrufern aus anderen Assemblys die Verwendung Ihrer Typen zu ermöglichen.

public class Customer
{
    public string Name { get; set; }

    public Customer(string name) => Name = name;
}

Der Klassenkörper enthält Felder, Eigenschaften, Methoden und Ereignisse, die zusammen als Klassenmitglieder bezeichnet werden. Der Name muss ein gültiger C# -Bezeichnername sein.

Objekte erstellen

Eine Klasse definiert einen Typ, ist aber kein Objekt selbst. Sie erstellen ein Objekt (eine Instanz der Klasse) mit dem new Schlüsselwort:

var customer = new Customer("Allison");
Console.WriteLine(customer.Name); // Allison

Die Variable customer enthält einen Verweis auf das Objekt, nicht das Objekt selbst. Sie können demselben Objekt mehrere Variablen zuweisen. Änderungen durch einen Verweis sind durch die andere sichtbar:

var c1 = new Customer("Grace");
var c2 = c1; // both variables reference the same object

c2.Name = "Hopper";
Console.WriteLine(c1.Name); // Hopper — c1 sees the change made through c2

Dieses Referenzfreigabeverhalten ist eine Unterscheidung zwischen Klassen und Strukturen. Bei Strukturierungen kopiert die Zuordnung die Daten. Wichtiger ist, dass Klassen die Vererbung unterstützen. Sie können Hierarchien erstellen, in denen abgeleitete Typen das Verhalten einer Basisklasse wiederverwenden und spezialisieren. Strukturen können nicht an Vererbungshierarchien teilnehmen. Weitere Informationen zur Unterscheidung finden Sie unter Werttypen und Referenztypen.

Konstruktoren und Initialisierung

Wenn Sie eine Instanz erstellen, sollen die zugehörigen Felder und Eigenschaften für nützliche Werte initialisiert werden. C# bietet verschiedene Ansätze: Feldinitialisierer, Konstruktorparameter, primäre Konstruktoren und erforderliche Eigenschaften.

Feldinitialisierer legen einen Standardwert direkt in der Felddeklaration fest:

public class Container
{
    private int _capacity = 10;
}

Feldinitialisierer weisen einem Feld oder einer Eigenschaft einen angemessenen Standardwert zu. Dies unterscheidet sie von den folgenden Ansätzen, bei denen Aufrufer den Anfangswert bereitstellen können.

Konstruktorparameter erfordern, dass die Aufrufer Werte bereitstellen.

public class Container
{
    private int _capacity;

    public Container(int capacity) => _capacity = capacity;
}

Primäre Konstruktoren (C# 12+) fügen der Klassendeklaration Parameter direkt hinzu. Diese Parameter sind im gesamten Klassenkörper verfügbar.

public class Container(int capacity)
{
    private int _capacity = capacity;
}

Primäre Konstruktoren und Feldinitialisierer können zusammenarbeiten: Der Feldinitialisierer _capacity = capacity verwendet den Primärkonstruktorparameter als Wert. Mit diesem Muster können Sie Konstruktorargumente in Feldern mit einer einzelnen, präzisen Deklaration erfassen.

Erforderliche Eigenschaften erzwingen, dass Aufrufer bestimmte Eigenschaften über einen Objektinitialisierer festlegen:

public class Person
{
    public required string FirstName { get; set; }
    public required string LastName { get; set; }
}
// var missing = new Person(); // Error: required properties not set
var person = new Person { FirstName = "Grace", LastName = "Hopper" };
Console.WriteLine($"{person.FirstName} {person.LastName}"); // Grace Hopper

Einen tieferen Einblick in Konstruktormuster, einschließlich Parameterüberprüfung und Konstruktorketten, finden Sie unter "Konstruktoren".

Statische Klassen

Eine static Klasse kann nicht instanziiert werden und enthält nur statische Member. Verwenden Sie statische Klassen, um Hilfsmethoden zu organisieren, die nicht für Instanzdaten verwendet werden:

static class MathHelpers
{
    public static double CircleCircumference(double radius) =>
        2 * Math.PI * radius;
}
double circumference = MathHelpers.CircleCircumference(5.0);
Console.WriteLine($"Circumference: {circumference:F2}"); // Circumference: 31.42

Die .NET Klassenbibliothek enthält viele statische Klassen wie Math und Console. Eine statische Klasse ist implizit versiegelt. Sie können sie nicht ableiten oder instanziieren.

Objektinitialisierer

Mit Objektinitialisierern können Sie Eigenschaften festlegen, wenn Sie ein Objekt erstellen, ohne einen Konstruktor für jede Kombination von Werten zu schreiben:

class ConnectionOptions
{
    public string Host { get; init; } = "localhost";
    public int Port { get; init; } = 80;
    public bool UseSsl { get; init; }
}
var options = new ConnectionOptions
{
    Host = "db.example.com",
    Port = 5432,
    UseSsl = true
};
Console.WriteLine($"{options.Host}:{options.Port} (SSL: {options.UseSsl})");
// db.example.com:5432 (SSL: True)

Objektinitialisierer funktionieren mit jeder zugänglichen Eigenschaft, die über einen set- oder init-Accessor verfügt. Sie werden auf natürliche Weise mit required-Eigenschaften und mit Konstruktoren kombiniert, die einige Parameter akzeptieren, während sie dem Aufrufer die Festlegung anderer überlassen.

Wenn es sich bei der Eigenschaft um eine Auflistung handelt, können Sie einen Auflistungsausdruck (C#-Verweis) verwenden, um dieses Objekt zu initialisieren.

Vererbung

Klassen unterstützen die Vererbung. Sie können eine neue Klasse definieren, die das Verhalten einer vorhandenen Klasse wiederverwendet, erweitert oder ändert. Die klasse, von der Sie erben, ist die Basisklasse, und die neue Klasse ist die abgeleitete Klasse:

var manager = new Manager("Satya", "Engineering");
Console.WriteLine($"{manager.Name} manages {manager.Department}");
// Satya manages Engineering

Eine Klasse kann von einer Basisklasse erben und mehrere Schnittstellen implementieren. Abgeleitete Klassen erben alle Member der Basisklasse mit Ausnahme von Konstruktoren. Weitere Informationen finden Sie unter Vererbung und Schnittstellen.

Siehe auch