Klassen und ObjekteClasses and objects

Klassen sind die grundlegendsten der C#-Typen.Classes are the most fundamental of C#’s types. Eine Klasse ist eine Datenstruktur, die einen Zustand (Felder) und Aktionen (Methoden und andere Funktionsmember) in einer einzigen Einheit kombiniert.A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. Eine Klasse stellt eine Definition für dynamisch erstellte Instanzen der Klasse, auch bekannt als Objekte bereit.A class provides a definition for dynamically created instances of the class, also known as objects. Klassen unterstützen Vererbung und Polymorphie. Dies sind Mechanismen, durch die abgeleitete Klassen erweitert und Basisklassen spezialisiert werden können.Classes support inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

Neue Klassen werden mithilfe von Klassendeklarationen erstellt.New classes are created using class declarations. Eine Klassendeklaration beginnt mit einem Header, der die Attribute und Modifizierer der Klasse, den Namen der Klasse, die Basisklasse (sofern vorhanden) und die von der Klasse implementierten Schnittstellen angibt.A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. Auf den Header folgt der Klassenkörper. Dieser besteht aus einer Liste der Memberdeklarationen, die zwischen den Trennzeichen { und } eingefügt werden.The header is followed by the class body, which consists of a list of member declarations written between the delimiters { and }.

Nachfolgend sehen Sie eine Deklaration einer einfachen Klasse namens Point:The following is a declaration of a simple class named Point:

public class Point
{
    public int x, y;
    public Point(int x, int y) 
    {
        this.x = x;
        this.y = y;
    }
}

Instanzen von Klassen werden mit dem new-Operator erstellt. Dieser reserviert Speicher für eine neue Instanz, ruft einen Konstruktor zum Initialisieren der Instanz auf und gibt einen Verweis auf die Instanz zurück.Instances of classes are created using the new operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. Mit den folgenden Anweisungen werden zwei Point-Objekte erstellt und Verweise auf diese Objekte in zwei Variablen gespeichert:The following statements create two Point objects and store references to those objects in two variables:

Point p1 = new Point(0, 0);
Point p2 = new Point(10, 20);

Der von einem Objekt belegte Speicher wird automatisch wieder freigegeben, wenn das Objekt nicht mehr erreichbar ist.The memory occupied by an object is automatically reclaimed when the object is no longer reachable. Es ist weder erforderlich noch möglich, die Zuweisung von Objekten in C# explizit aufzuheben.It is neither necessary nor possible to explicitly deallocate objects in C#.

MemberMembers

Die Member einer Klasse sind entweder statische Member oder Instanzmember.The members of a class are either static members or instance members. Statische Member gehören zu Klassen, Instanzmember gehören zu Objekten (Instanzen von Klassen).Static members belong to classes, and instance members belong to objects (instances of classes).

Nachfolgend finden Sie einen Überblick über die Memberarten, die eine Klasse enthalten kann.The following provides an overview of the kinds of members a class can contain.

  • KonstantenConstants
    • Konstante Werte, die der Klasse zugeordnet sindConstant values associated with the class
  • FelderFields
    • Variablen der KlasseVariables of the class
  • MethodenMethods
    • Berechnungen und Aktionen, die von der Klasse ausgeführt werdenComputations and actions that can be performed by the class
  • EigenschaftenProperties
    • Aktionen im Zusammenhang mit dem Lesen und Schreiben von benannten Eigenschaften der KlasseActions associated with reading and writing named properties of the class
  • IndexerIndexers
    • Aktionen im Zusammenhang mit dem Indizieren von Instanzen der Klasse, z.B. einem ArrayActions associated with indexing instances of the class like an array
  • EreignisseEvents
    • Benachrichtigungen, die von der Klasse generiert werden könnenNotifications that can be generated by the class
  • OperatorenOperators
    • Operatoren für Konvertierungen und Ausdrücke, die von der Klasse unterstützt werdenConversions and expression operators supported by the class
  • KonstruktorenConstructors
    • Aktionen, die zum Initialisieren von Instanzen der Klasse oder der Klasse selbst benötigt werdenActions required to initialize instances of the class or the class itself
  • FinalizerFinalizers
    • Aktionen, die ausgeführt werden, bevor Instanzen der Klasse dauerhaft verworfen werdenActions to perform before instances of the class are permanently discarded
  • TypenTypes
    • Geschachtelte Typen, die von der Klasse deklariert werdenNested types declared by the class

ZugriffAccessibility

Jeder Member einer Klasse ist mit einem Zugriff verknüpft, der die Regionen des Programmtexts steuert, die auf den Member zugreifen können.Each member of a class has an associated accessibility, which controls the regions of program text that are able to access the member. Es gibt fünf mögliche Formen des Zugriffs.There are five possible forms of accessibility. Diese werden nachfolgend zusammengefasst.These are summarized below.

  • public
    • Der Zugriff ist nicht eingeschränkt.Access not limited
  • protected
    • Der Zugriff ist auf diese Klasse oder auf von dieser Klasse abgeleitete Klassen beschränkt.Access limited to this class or classes derived from this class
  • internal
    • Der Zugriff ist auf die aktuelle Assembly beschränkt (.exe, .dll, usw.)Access limited to the current assembly (.exe, .dll, etc.)
  • protected internal
    • Der Zugriff ist auf die enthaltende Klasse oder auf Klassen beschränkt, die von der enthaltenden Klasse abgeleitet sind.Access limited to the containing class or classes derived from the containing class
  • private
    • Der Zugriff ist auf diese Klasse beschränkt.Access limited to this class
  • private protected
    • Zugriff eingeschränkt auf die enthaltende Klasse oder Klassen abgeleitet aus dem enthaltenden Typ innerhalb die gleiche assemblyAccess limited to the containing class or classes derived from the containing type withing the same assembly

TypparameterType parameters

Eine Klassendefinition kann einen Satz an Typparametern angeben, indem eine Liste der Typparameternamen in spitzen Klammern an den Klassennamen angehängt wird.A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. Die Typparameter können dann im Körper der Klassendeklarationen zum Definieren der Klassenmember verwendet werden.The type parameters can then be used in the body of the class declarations to define the members of the class. Im folgenden Beispiel lauten die Typparameter von Pair TFirst und TSecond:In the following example, the type parameters of Pair are TFirst and TSecond:

public class Pair<TFirst,TSecond>
{
    public TFirst First;
    public TSecond Second;
}

Ein Klassentyp, der zum Akzeptieren von Typparametern deklariert wird, wird als generischer Klassentyp bezeichnet.A class type that is declared to take type parameters is called a generic class type. Struktur-, Schnittstellen- und Delegattypen können auch generisch sein.Struct, interface and delegate types can also be generic. Wenn die generische Klasse verwendet wird, müssen für jeden der Typparameter Typargumente angegeben werden:When the generic class is used, type arguments must be provided for each of the type parameters:

Pair<int,string> pair = new Pair<int,string> { First = 1, Second = "two" };
int i = pair.First;     // TFirst is int
string s = pair.Second; // TSecond is string

Ein generischer Typ, für den Typargumente angegeben wurden (siehe Pair<int,string> oben), wird als konstruierter Typ bezeichnet.A generic type with type arguments provided, like Pair<int,string> above, is called a constructed type.

BasisklassenBase classes

Eine Klassendeklaration kann eine Basisklasse angeben, indem ein Doppelpunkt und der Name der Basisklasse an den Klassennamen und die Typparameter angehängt wird.A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Das Auslassen einer Basisklassenspezifikation ist dasselbe wie eine Ableitung vom Typ object.Omitting a base class specification is the same as deriving from type object. Im folgenden Beispiel ist Point die Basisklasse von Point3D, und die Basisklasse von Point ist object:In the following example, the base class of Point3D is Point, and the base class of Point is object:

public class Point
{
    public int x, y;
    public Point(int x, int y) 
    {
        this.x = x;
        this.y = y;
    }
}
public class Point3D: Point
{
    public int z;
    public Point3D(int x, int y, int z) : 
        base(x, y) 
    {
        this.z = z;
    }
}

Eine Klasse erbt die Member der zugehörigen Basisklasse.A class inherits the members of its base class. Vererbung bedeutet, dass eine Klasse implizit alle Member dieser Basisklasse enthält, mit Ausnahme der Instanzkonstruktoren und der statischen Konstruktoren sowie der Finalizer der Basisklasse.Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the finalizers of the base class. Eine abgeleitete Klasse kann den geerbten Membern neue Member hinzufügen, aber die Definition eines geerbten Members kann nicht entfernt werden.A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member. Im vorherigen Beispiel erbt Point3D die Felder x und y von Point, und jede Point3D-Instanz enthält drei Felder: x, y und z.In the previous example, Point3D inherits the x and y fields from Point, and every Point3D instance contains three fields, x, y, and z.

Ein Klassentyp kann implizit in einen beliebigen zugehörigen Basisklassentyp konvertiert werden.An implicit conversion exists from a class type to any of its base class types. Deshalb kann eine Variable eines Klassentyps auf eine Instanz dieser Klasse oder auf eine Instanz einer beliebigen abgeleiteten Klasse verweisen.Therefore, a variable of a class type can reference an instance of that class or an instance of any derived class. Beispielsweise kann in den vorherigen Klassendeklarationen eine Variable vom Typ Point entweder auf Point oder auf Point3D verweisen:For example, given the previous class declarations, a variable of type Point can reference either a Point or a Point3D:

Point a = new Point(10, 20);
Point b = new Point3D(10, 20, 30);

FelderFields

Ein Feld ist eine Variable, die einer Klasse oder einer Instanz einer Klasse zugeordnet ist.A field is a variable that is associated with a class or with an instance of a class.

Ein Feld, das mit dem static-Modifizierer deklariert wurde, definiert ein statisches Feld.A field declared with the static modifier defines a static field. Ein statisches Feld identifiziert genau einen Speicherort.A static field identifies exactly one storage location. Unabhängig davon, wie viele Instanzen einer Klasse erstellt werden, gibt es nur eine Kopie eines statischen Felds.No matter how many instances of a class are created, there is only ever one copy of a static field.

Ein Feld, das ohne den static-Modifizierer deklariert wurde, definiert ein Instanzfeld.A field declared without the static modifier defines an instance field. Jede Instanz einer Klasse enthält eine separate Kopie aller Instanzfelder dieser Klasse.Every instance of a class contains a separate copy of all the instance fields of that class.

Im folgenden Beispiel weist jede Instanz der Color-Klasse eine separate Kopie der Instanzfelder r, g und b auf, aber es gibt nur eine Kopie der statischen Felder Black, White, Red, Green und Blue:In the following example, each instance of the Color class has a separate copy of the r, g, and b instance fields, but there is only one copy of the Black, White, Red, Green, and Blue static fields:

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte r, g, b;
    public Color(byte r, byte g, byte b) 
    {
        this.r = r;
        this.g = g;
        this.b = b;
    }
}

Wie im vorherigen Beispiel gezeigt, können schreibgeschützte Felder mit einem readonly-Modifizierer deklariert werden.As shown in the previous example, read-only fields may be declared with a readonly modifier. Einem readonly-Feld können Werte nur als Teil einer Deklaration oder in einem Konstruktor derselben Klasse zugewiesen werden.Assignment to a readonly field can only occur as part of the field’s declaration or in a constructor in the same class.

MethodenMethods

Eine Methode ist ein Member, das eine Berechnung oder eine Aktion implementiert, die durch ein Objekt oder eine Klasse durchgeführt werden kann.A method is a member that implements a computation or action that can be performed by an object or class. Auf statische Methoden wird über die Klasse zugegriffen.Static methods are accessed through the class. Auf Instanzmethoden wird über Instanzen der Klasse zugegriffen.Instance methods are accessed through instances of the class.

Methoden können über eine Liste von Parametern – diese repräsentieren die an die Methode übergebene Werte oder Variablenverweise – sowie über einen Rückgabetyp verfügen, der den Typ des Werts angibt, der von der Methode berechnet und zurückgegeben wird.Methods may have a list of parameters, which represent values or variable references passed to the method, and a return type, which specifies the type of the value computed and returned by the method. Der Rückgabetyp einer Methode lautet void, wenn kein Wert zurückgegeben wird.A method’s return type is void if it does not return a value.

Ebenso wie Typen können Methoden einen Satz an Typparametern aufweisen, für den beim Aufruf der Methode Typargumente angegeben werden müssen.Like types, methods may also have a set of type parameters, for which type arguments must be specified when the method is called. Im Gegensatz zu Typen können die Typargumente häufig aus den Argumenten eines Methodenaufrufs abgeleitet werden und müssen nicht explizit angegeben werden.Unlike types, the type arguments can often be inferred from the arguments of a method call and need not be explicitly given.

Die Signatur einer Methode muss innerhalb der Klasse eindeutig sein, in der die Methode deklariert ist.The signature of a method must be unique in the class in which the method is declared. Die Signatur einer Methode besteht aus dem Namen der Methode, der Anzahl von Typparametern und der Anzahl, den Modifizierern und den Typen der zugehörigen Parameter.The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. Die Signatur einer Methode umfasst nicht den Rückgabetyp.The signature of a method does not include the return type.

ParameterParameters

Parameter werden dazu verwendet, Werte oder Variablenverweise an Methoden zu übergeben.Parameters are used to pass values or variable references to methods. Die Parameter einer Methode erhalten ihre tatsächlichen Werte über Argumente, die angegeben werden, wenn die Methode aufgerufen wird.The parameters of a method get their actual values from the arguments that are specified when the method is invoked. Es gibt vier Arten von Parametern: Wertparameter, Verweisparameter, Ausgabeparameter und Parameterarrays.There are four kinds of parameters: value parameters, reference parameters, output parameters, and parameter arrays.

Ein Wertparameter wird zum Übergeben von Eingabeargumenten verwendet.A value parameter is used for passing input arguments. Ein Wertparameter entspricht einer lokalen Variablen, die ihren Anfangswert von dem Argument erhält, das für den Parameter übergeben wurde.A value parameter corresponds to a local variable that gets its initial value from the argument that was passed for the parameter. Änderungen an einem Wertparameter wirken sich nicht auf das Argument aus, das für den Parameter übergeben wurde.Modifications to a value parameter do not affect the argument that was passed for the parameter.

Wertparameter können optional sein, indem ein Standardwert festgelegt wird, damit die zugehörigen Argumente weggelassen werden können.Value parameters can be optional, by specifying a default value so that corresponding arguments can be omitted.

Ein Verweisparameter wird zum Übergeben von Argumenten als Verweis verwendet.A reference parameter is used for passing arguments by reference. Das für einen Verweisparameter übergebene Argument muss eine Variable mit eindeutigem Wert sein, und während der Ausführung der Methode repräsentiert der Verweisparameter denselben Speicherort wie die Argumentvariable.The argument passed for a reference parameter must be a variable with a definite value, and during execution of the method, the reference parameter represents the same storage location as the argument variable. Ein Verweisparameter wird mit dem ref-Modifizierer deklariert.A reference parameter is declared with the ref modifier. Das folgende Beispiel veranschaulicht die Verwendung des ref-Parameters.The following example shows the use of ref parameters.

using System;
class RefExample
{
    static void Swap(ref int x, ref int y) 
    {
        int temp = x;
        x = y;
        y = temp;
    }
    public static void SwapExample() 
    {
        int i = 1, j = 2;
        Swap(ref i, ref j);
        Console.WriteLine($"{i} {j}");    // Outputs "2 1"
    }
}

Ein Ausgabeparameter wird zum Übergeben von Argumenten als Verweis verwendet.An output parameter is used for passing arguments by reference. Er ist einem Verweisparameter ähnlich, außer dass er nicht erfordert, dass Sie explizit dem vom Aufrufer bereitgestellten Argument einen Wert zuweisen.It's similar to a reference parameter, except that it doesn't require that you explicitly assign a value to the caller-provided argument. Ein Ausgabeparameter wird mit dem out-Modifizierer deklariert.An output parameter is declared with the out modifier. Das folgende Beispiel zeigt die Verwendung von out-Parametern mithilfe der in C# 7 eingeführten Syntax.The following example shows the use of out parameters using the syntax introduced in C# 7.

    using System;
    class OutExample
    {
        static void Divide(int x, int y, out int result, out int remainder) 
        {
            result = x / y;
            remainder = x % y;
        }
        public static void OutUsage() 
        {
            Divide(10, 3, out int res, out int rem);
            Console.WriteLine("{0} {1}", res, rem);	// Outputs "3 1"
        }
    }
}

Ein Parameterarray ermöglicht es, eine variable Anzahl von Argumenten an eine Methode zu übergeben.A parameter array permits a variable number of arguments to be passed to a method. Ein Parameterarray wird mit dem params-Modifizierer deklariert.A parameter array is declared with the params modifier. Nur der letzte Parameter einer Methode kann ein Parameterarray sein, und es muss sich um ein eindimensionales Parameterarray handeln.Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. Die Write- und WriteLine-Methoden der System.Console-Klasse sind gute Beispiele für die Verwendung eines Parameterarrays.The Write and WriteLine methods of the System.Console class are good examples of parameter array usage. Sie werden folgendermaßen deklariert.They are declared as follows.

public class Console
{
    public static void Write(string fmt, params object[] args) { }
    public static void WriteLine(string fmt, params object[] args) { }
    // ...
}

Innerhalb einer Methode mit einem Parameterarray verhält sich das Parameterarray wie ein regulärer Parameter des Arraytyps.Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. Beim Aufruf einer Methode mit einem Parameterarray ist es jedoch möglich, entweder ein einzelnes Argument des Parameterarraytyps oder eine beliebige Anzahl von Argumenten des Elementtyps des Parameterarrays zu übergeben.However, in an invocation of a method with a parameter array, it is possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. Im letzteren Fall wird automatisch eine Arrayinstanz erstellt und mit den vorgegebenen Argumenten initialisiert.In the latter case, an array instance is automatically created and initialized with the given arguments. Dieses Beispiel:This example

Console.WriteLine("x={0} y={1} z={2}", x, y, z);

...entspricht dem folgenden Code:is equivalent to writing the following.

string s = "x={0} y={1} z={2}";
object[] args = new object[3];
args[0] = x;
args[1] = y;
args[2] = z;
Console.WriteLine(s, args);

Methodenkörper und lokale VariablenMethod body and local variables

Der Methodenkörper gibt die Anweisungen an, die beim Aufruf der Methode ausgeführt werden sollen.A method’s body specifies the statements to execute when the method is invoked.

Ein Methodenkörper kann Variablen deklarieren, die für den Aufruf der Methode spezifisch sind.A method body can declare variables that are specific to the invocation of the method. Diese Variable werden lokale Variablen genannt.Such variables are called local variables. Die Deklaration einer lokalen Variable gibt einen Typnamen, einen Variablennamen und eventuell einen Anfangswert an.A local variable declaration specifies a type name, a variable name, and possibly an initial value. Im folgenden Beispiel wird eine lokale Variable i mit einem Anfangswert von 0 und einer lokalen Variablen j ohne Anfangswert deklariert.The following example declares a local variable i with an initial value of zero and a local variable j with no initial value.

using System;
class Squares
{
    public static void WriteSquares() 
    {
        int i = 0;
        int j;
        while (i < 10) 
        {
            j = i * i;
            Console.WriteLine($"{i} x {i} = {j}");
            i = i + 1;
        }
    }
}

In C# muss eine lokale Variable definitiv zugewiesen sein, bevor ihr Wert abgerufen werden kann.C# requires a local variable to be definitely assigned before its value can be obtained. Wenn beispielsweise die vorherige Deklaration von i keinen Anfangswert enthielte, würde der Compiler bei der nachfolgenden Verwendung von i einen Fehler melden, weil i zu diesen Zeitpunkten im Programm nicht definitiv zugewiesen wäre.For example, if the declaration of the previous i did not include an initial value, the compiler would report an error for the subsequent usages of i because i would not be definitely assigned at those points in the program.

Eine Methode kann return-Anweisungen verwenden, um die Steuerung an den zugehörigen Aufrufer zurückzugeben.A method can use return statements to return control to its caller. In einer Methode, die void zurückgibt, können return-Anweisungen keinen Ausdruck angeben.In a method returning void, return statements cannot specify an expression. In einer Methode, die nicht „void“ zurückgibt, müssenreturn-Anweisungen einen Ausdruck enthalten, der den Rückgabewert berechnet.In a method returning non-void, return statements must include an expression that computes the return value.

Statische Methoden und InstanzmethodenStatic and instance methods

Eine mit einem statischen Modifizierer deklarierte Methode ist eine statische Methode.A method declared with a static modifier is a static method. Eine statische Methode führt keine Vorgänge für eine spezifische Instanz aus und kann nur direkt auf statische Member zugreifen.A static method does not operate on a specific instance and can only directly access static members.

Eine ohne einen statischen Modifizierer deklarierte Methode ist eine Instanzmethode.A method declared without a static modifier is an instance method. Eine Instanzmethode führt Vorgänge für eine spezifische Instanz aus und kann sowohl auf statische Member als auch auf Instanzmember zugreifen.An instance method operates on a specific instance and can access both static and instance members. Auf die Instanz, für die eine Instanzmethode aufgerufen wurde, kann explizit als this zugegriffen werden.The instance on which an instance method was invoked can be explicitly accessed as this. Es ist ein Fehler, in einer statischen Methode auf this zu verweisen.It is an error to refer to this in a static method.

Die folgende Entity-Klasse umfasst sowohl statische Member als auch Instanzmember.The following Entity class has both static and instance members.

class Entity
{
    static int nextSerialNo;
    int serialNo;
    public Entity() 
    {
        serialNo = nextSerialNo++;
    }
    public int GetSerialNo() 
    {
        return serialNo;
    }
    public static int GetNextSerialNo() 
    {
        return nextSerialNo;
    }
    public static void SetNextSerialNo(int value) 
    {
        nextSerialNo = value;
    }
}

Jede Entity-Instanz enthält eine Seriennummer (und vermutlich weitere Informationen, die hier nicht angezeigt werden).Each Entity instance contains a serial number (and presumably some other information that is not shown here). Der Entity-Konstruktor (der einer Instanzmethode ähnelt) initialisiert die neue Instanz mit der nächsten verfügbaren Seriennummer.The Entity constructor (which is like an instance method) initializes the new instance with the next available serial number. Da der Konstruktor ein Instanzmember ist, kann er sowohl auf das serialNo-Instanzfeld als auch auf das statische nextSerialNo-Feld zugreifen.Because the constructor is an instance member, it is permitted to access both the serialNo instance field and the nextSerialNo static field.

Die statischen Methoden GetNextSerialNo und SetNextSerialNo können auf das statische Feld nextSerialNo zugreifen, aber es wäre ein Fehler, über diese Methoden direkt auf das Instanzfeld serialNo zuzugreifen.The GetNextSerialNo and SetNextSerialNo static methods can access the nextSerialNo static field, but it would be an error for them to directly access the serialNo instance field.

Das folgende Beispiel zeigt die Verwendung der Entity-Klasse.The following example shows the use of the Entity class.

using System;
class EntityExample
{
    public static void Usage() 
    {
        Entity.SetNextSerialNo(1000);
        Entity e1 = new Entity();
        Entity e2 = new Entity();
        Console.WriteLine(e1.GetSerialNo());            // Outputs "1000"
        Console.WriteLine(e2.GetSerialNo());            // Outputs "1001"
        Console.WriteLine(Entity.GetNextSerialNo());    // Outputs "1002"
    }
}

Beachten Sie, dass die statischen Methoden SetNextSerialNo und GetNextSerialNo für die Klasse aufgerufen werden, während die GetSerialNo-Instanzmethode für Instanzen der Klasse aufgerufen wird.Note that the SetNextSerialNo and GetNextSerialNo static methods are invoked on the class whereas the GetSerialNo instance method is invoked on instances of the class.

Virtuelle, überschriebene und abstrakte MethodenVirtual, override, and abstract methods

Wenn die Deklaration einer Instanzmethode einen virtual-Modifizierer enthält, wird die Methode als virtuelle Methode bezeichnet.When an instance method declaration includes a virtual modifier, the method is said to be a virtual method. Ist kein virtual-Modifizierer vorhanden, spricht man von einer nicht virtuellen Methode.When no virtual modifier is present, the method is said to be a nonvirtual method.

Beim Aufruf einer virtuellen Methode bestimmt der Laufzeittyp der Instanz, für die der Aufruf erfolgt, die tatsächlich aufzurufende Methodenimplementierung.When a virtual method is invoked, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke. Beim Aufruf einer nicht virtuellen Methode ist der Kompilierzeittyp der bestimmende Faktor.In a nonvirtual method invocation, the compile-time type of the instance is the determining factor.

Eine virtuelle Methode kann in einer abgeleiteten Klasse nicht überschrieben werden.A virtual method can be overridden in a derived class. Wenn eine Instanzmethodendeklaration einen override-Modifizierer enthält, überschreibt die Methode eine geerbte virtuelle Methode mit derselben Signatur.When an instance method declaration includes an override modifier, the method overrides an inherited virtual method with the same signature. Während eine Deklaration einer virtuellen Methode eine neue Methode einführt, spezialisiert eine Deklaration einer überschriebenen Methode eine vorhandene geerbte virtuelle Methode, indem eine neue Implementierung dieser Methode bereitgestellt wird.Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

Eine abstrakte Methode ist eine virtuelle Methode ohne Implementierung.An abstract method is a virtual method with no implementation. Eine abstrakte Methode wird mit dem abstract-Modifizierer deklariert und ist nur in einer Klasse erlaubt, die auch als abstrakt deklariert wurde.An abstract method is declared with the abstract modifier and is permitted only in a class that is also declared abstract. Eine abstrakte Methode muss in jeder nicht abstrakten abgeleiteten Klasse überschrieben werden.An abstract method must be overridden in every non-abstract derived class.

Im folgenden Beispiel wird die abstrakte Klasse Expression deklariert, die einen Ausdrucksbaumstrukturknoten sowie drei abgeleitete Klassen repräsentiert: Constant, VariableReference und Operation. Diese implementieren Ausdrucksbaumstrukturknoten für Konstanten, variable Verweise und arithmetische Operationen.The following example declares an abstract class, Expression, which represents an expression tree node, and three derived classes, Constant, VariableReference, and Operation, which implement expression tree nodes for constants, variable references, and arithmetic operations. (Dies ähnelt den Ausdrucksbaumstrukturtypen, sollte aber mit diesen nicht verwechselt werden.)(This is similar to, but not to be confused with the expression tree types).

using System;
using System.Collections.Generic;
public abstract class Expression
{
    public abstract double Evaluate(Dictionary<string,object> vars);
}
public class Constant: Expression
{
    double value;
    public Constant(double value) 
    {
        this.value = value;
    }
    public override double Evaluate(Dictionary<string,object> vars) 
    {
        return value;
    }
}
public class VariableReference: Expression
{
    string name;
    public VariableReference(string name) 
    {
        this.name = name;
    }
    public override double Evaluate(Dictionary<string,object> vars) 
    {
        object value = vars[name];
        if (value == null) 
        {
            throw new Exception("Unknown variable: " + name);
        }
        return Convert.ToDouble(value);
    }
}
public class Operation: Expression
{
    Expression left;
    char op;
    Expression right;
    public Operation(Expression left, char op, Expression right) 
    {
        this.left = left;
        this.op = op;
        this.right = right;
    }
    public override double Evaluate(Dictionary<string,object> vars) 
    {
        double x = left.Evaluate(vars);
        double y = right.Evaluate(vars);
        switch (op) {
            case '+': return x + y;
            case '-': return x - y;
            case '*': return x * y;
            case '/': return x / y;
        }
        throw new Exception("Unknown operator");
    }
}

Die vorherigen vier Klassen können zum Modellieren arithmetischer Ausdrücke verwendet werden.The previous four classes can be used to model arithmetic expressions. Beispielsweise kann mithilfe von Instanzen dieser Klassen der Ausdruck x + 3 folgendermaßen dargestellt werden.For example, using instances of these classes, the expression x + 3 can be represented as follows.

Expression e = new Operation(
    new VariableReference("x"),
    '+',
    new Constant(3));

Die Evaluate-Methode einer Expression-Instanz wird aufgerufen, um den vorgegebenen Ausdruck auszuwerten und einen double-Wert zu generieren.The Evaluate method of an Expression instance is invoked to evaluate the given expression and produce a double value. Die Methode verwendet ein Dictionary-Argument, das Variablennamen (als Schlüssel der Einträge) und Werte (als Werte der Einträge) enthält.The method takes a Dictionary argument that contains variable names (as keys of the entries) and values (as values of the entries). Da Evaluate eine abstrakte Methode ist, müssen nicht-abstrakte Klassen, die von Expression abgeleitet sind, Evaluate außer Kraft setzen.Because Evaluate is an abstract method, non-abstract classes derived from Expression must override Evaluate.

Eine Implementierung von Constant für Evaluate gibt lediglich die gespeicherte Konstante zurück.A Constant's implementation of Evaluate simply returns the stored constant. Eine Implementierung von VariableReference sucht im Wörterbuch nach dem Variablennamen und gibt den Ergebniswert zurück.A VariableReference's implementation looks up the variable name in the dictionary and returns the resulting value. Eine Implementierung von Operation wertet zunächst (durch einen rekursiven Aufruf der zugehörigen Evaluate-Methoden) den linken und rechten Operanden aus und führt dann die vorgegebene arithmetische Operation aus.An Operation's implementation first evaluates the left and right operands (by recursively invoking their Evaluate methods) and then performs the given arithmetic operation.

Das folgende Programm verwendet die Expression-Klassen zum Auswerten des Ausdrucks x * (y + 2) für verschiedene Werte von x und y.The following program uses the Expression classes to evaluate the expression x * (y + 2) for different values of x and y.

using System;
using System.Collections.Generic;
class InheritanceExample
{
    public static void ExampleUsage() 
    {
        Expression e = new Operation(
            new VariableReference("x"),
            '*',
            new Operation(
                new VariableReference("y"),
                '+',
                new Constant(2)
            )
        );
        Dictionary<string,object> vars = new Dictionary<string, object>();
        vars["x"] = 3;
        vars["y"] = 5;
        Console.WriteLine(e.Evaluate(vars));		// Outputs "21"
        vars["x"] = 1.5;
        vars["y"] = 9;
        Console.WriteLine(e.Evaluate(vars));		// Outputs "16.5"
    }
}   

MethodenüberladungMethod overloading

Das Überladen von Methoden macht es möglich, dass mehrere Methoden in derselben Klasse denselben Namen verwenden, solange sie eindeutige Signaturen aufweisen.Method overloading permits multiple methods in the same class to have the same name as long as they have unique signatures. Beim Kompilieren des Aufrufs einer überladenen Methode verwendet der Compiler die Überladungsauflösung, um die spezifische Methode zu ermitteln, die aufgerufen werden soll.When compiling an invocation of an overloaded method, the compiler uses overload resolution to determine the specific method to invoke. Mithilfe der Überladungsauflösung wird die Methode ermittelt, die den Argumenten am besten entspricht, bzw. es wird ein Fehler ausgegeben, wenn keine passende Methode gefunden wird.Overload resolution finds the one method that best matches the arguments or reports an error if no single best match can be found. Das folgende Beispiel zeigt die Verwendung der Überladungsauflösung.The following example shows overload resolution in effect. Der Kommentar für jeden Aufruf in der Main-Methode zeigt, welche Methode tatsächlich aufgerufen wird.The comment for each invocation in the Main method shows which method is actually invoked.

using System;
class OverloadingExample
{
    static void F() 
    {
        Console.WriteLine("F()");
    }
    static void F(object x) 
    {
        Console.WriteLine("F(object)");
    }
    static void F(int x) 
    {
        Console.WriteLine("F(int)");
    }
    static void F(double x) 
    {
        Console.WriteLine("F(double)");
    }
    static void F<T>(T x) 
    {
        Console.WriteLine("F<T>(T)");
    }
    static void F(double x, double y) 
    {
        Console.WriteLine("F(double, double)");
    }
    public static void UsageExample()
    {
        F();            // Invokes F()
        F(1);           // Invokes F(int)
        F(1.0);         // Invokes F(double)
        F("abc");       // Invokes F<string>(string)
        F((double)1);   // Invokes F(double)
        F((object)1);   // Invokes F(object)
        F<int>(1);      // Invokes F<int>(int)
        F(1, 1);        // Invokes F(double, double)
    }
}

Wie im Beispiel gezeigt, kann eine bestimmte Methode immer ausgewählt werden, indem die Argumente explizit in die passenden Parametertypen konvertiert und/oder explizit Typargumente angegeben werden.As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and/or explicitly supplying type arguments.

Andere FunktionsmemberOther function members

Member, die ausführbaren Code enthalten, werden als Funktionsmember einer Klasse bezeichnet.Members that contain executable code are collectively known as the function members of a class. In den vorangegangenen Abschnitten wurden die Methoden beschrieben, die wichtigste Form der Funktionsmember.The preceding section describes methods, which are the primary kind of function members. In diesem Abschnitt werden die weiteren Funktionsmember behandelt, die C# unterstützt: Konstruktoren, Eigenschaften, Indexer, Ereignisse, Operatoren und Finalizer.This section describes the other kinds of function members supported by C#: constructors, properties, indexers, events, operators, and finalizers.

Das folgende Beispiel zeigt eine generische Klasse namens List, die eine wachsende Liste von Objekten implementiert.The following shows a generic class called List, which implements a growable list of objects. Die Klasse enthält verschiedene Beispiele der gängigsten Arten von Funktionsmembern.The class contains several examples of the most common kinds of function members.

public class List<T>
{
    // Constant
    const int defaultCapacity = 4;

    // Fields
    T[] items;
    int count;

    // Constructor
    public List(int capacity = defaultCapacity) 
    {
        items = new T[capacity];
    }

    // Properties
    public int Count => count; 

    public int Capacity 
    {
        get { return items.Length; }
        set 
        {
            if (value < count) value = count;
            if (value != items.Length) 
            {
                T[] newItems = new T[value];
                Array.Copy(items, 0, newItems, 0, count);
                items = newItems;
            }
        }
    }

    // Indexer
    public T this[int index] 
    {
        get 
        {
            return items[index];
        }
        set 
        {
            items[index] = value;
            OnChanged();
        }
    }
    
    // Methods
    public void Add(T item) 
    {
        if (count == Capacity) Capacity = count * 2;
        items[count] = item;
        count++;
        OnChanged();
    }
    protected virtual void OnChanged() =>
        Changed?.Invoke(this, EventArgs.Empty);

    public override bool Equals(object other) =>
        Equals(this, other as List<T>);

    static bool Equals(List<T> a, List<T> b) 
    {
        if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null);
        if (Object.ReferenceEquals(b, null) || a.count != b.count)
            return false;
        for (int i = 0; i < a.count; i++) 
        {
            if (!object.Equals(a.items[i], b.items[i])) 
            {
                return false;
            }
        }
    return true;
    }

    // Event
    public event EventHandler Changed;

    // Operators
    public static bool operator ==(List<T> a, List<T> b) => 
        Equals(a, b);

    public static bool operator !=(List<T> a, List<T> b) => 
        !Equals(a, b);
}

KonstruktorenConstructors

C# unterstützt sowohl Instanzkonstruktoren als auch statische Konstruktoren.C# supports both instance and static constructors. Ein Instanzkonstruktor ist ein Member, der die erforderlichen Aktionen zum Initialisieren einer Instanz einer Klasse implementiert.An instance constructor is a member that implements the actions required to initialize an instance of a class. Ein statischer Konstruktor ist ein Member, der die zum Initialisieren einer Klasse erforderlichen Aktionen implementiert, um die Klasse beim ersten Laden selbst zu initialisieren.A static constructor is a member that implements the actions required to initialize a class itself when it is first loaded.

Ein Konstruktor wird wie eine Methode ohne Rückgabetyp und mit demselben Namen wie die enthaltende Klasse deklariert.A constructor is declared like a method with no return type and the same name as the containing class. Wenn eine Konstruktordeklaration einen static-Modifizierer enthält, deklariert sie einen statischen Konstruktor.If a constructor declaration includes a static modifier, it declares a static constructor. Andernfalls wird ein Instanzkonstruktor deklariert.Otherwise, it declares an instance constructor.

Instanzkonstruktoren können überladen werden und optionale Parameter verwenden.Instance constructors can be overloaded, and can have optional parameters. Beispielsweise deklariert die List<T>-Klasse zwei Instanzkonstruktoren, einen ohne Parameter und einen weiteren mit einem int-Parameter.For example, the List<T> class declares two instance constructors, one with no parameters and one that takes an int parameter. Instanzkonstruktoren werden über den new-Operator aufgerufen.Instance constructors are invoked using the new operator. Die folgenden Anweisungen weisen zwei Instanzen von List<string> unter Verwendung des Konstruktors der List-Klasse zu, mit dem optionalen Argument und ohne das optionale Argument.The following statements allocate two List<string> instances using the constructor of the List class with and without the optional argument.

List<string> list1 = new List<string>();
List<string> list2 = new List<string>(10);

Im Gegensatz zu anderen Members werden Instanzkonstruktoren nicht geerbt, und eine Klasse weist keine anderen Instanzkonstruktoren auf als diejenigen, die tatsächlich in der Klasse deklariert wurden.Unlike other members, instance constructors are not inherited, and a class has no instance constructors other than those actually declared in the class. Wenn kein Instanzkonstruktor für eine Klasse angegeben ist, wird automatisch ein leerer Instanzkonstruktor ohne Parameter bereitgestellt.If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided.

EigenschaftenProperties

Eigenschaften sind eine natürliche Erweiterung der Felder.Properties are a natural extension of fields. Beide sind benannte Member mit zugeordneten Typen, und für den Zugriff auf Felder und Eigenschaften wird dieselbe Syntax verwendet.Both are named members with associated types, and the syntax for accessing fields and properties is the same. Im Gegensatz zu Feldern bezeichnen Eigenschaften jedoch keine Speicherorte.However, unlike fields, properties do not denote storage locations. Stattdessen verfügen Eigenschaften über Accessors zum Angeben der Anweisungen, die beim Lesen oder Schreiben ihrer Werte ausgeführt werden sollen.Instead, properties have accessors that specify the statements to be executed when their values are read or written.

Eine Eigenschaft wird wie ein Feld deklariert, abgesehen davon, dass die Deklaration nicht auf ein Semikolon, sondern auf einen get- und/oder einen set-Accessor endet, der von den Trennzeichen { und } umschlossen wird.A property is declared like a field, except that the declaration ends with a get accessor and/or a set accessor written between the delimiters { and } instead of ending in a semicolon. Eine Eigenschaft, die sowohl einen get- als auch einen set-Accessor aufweist, ist eine Eigenschaft mit Lese- und Schreibzugriff. Eine Eigenschaft, die nur einen get-Accessor aufweist, ist schreibgeschützt, eine Eigenschaft, die nur einen set-Accessor aufweist, ist lesegeschützt.A property that has both a get accessor and a set accessor is a read-write property, a property that has only a get accessor is a read-only property, and a property that has only a set accessor is a write-only property.

Ein get-Accessor entspricht einer Methode ohne Parameter mit einem Rückgabewert des Eigenschaftstyps.A get accessor corresponds to a parameterless method with a return value of the property type. Wenn eine Eigenschaft kein Ziel einer Zuweisung ist, sondern in einem Ausdruck referenziert wird, wird der get-Accessor der Eigenschaft aufgerufen, um ihren Wert zu berechnen.Except as the target of an assignment, when a property is referenced in an expression, the get accessor of the property is invoked to compute the value of the property.

Ein set-Accessor entspricht einer Methode mit einem einzigen Parameter namens „value“ ohne Rückgabetyp.A set accessor corresponds to a method with a single parameter named value and no return type. Wenn auf eine Eigenschaft als Ziel einer Zuweisung der als Operand ++ oder -- verwiesen wird, erfolgt der Aufruf des set-Accessors mit einem Argument, das den neuen Wert bereitstellt.When a property is referenced as the target of an assignment or as the operand of ++ or --, the set accessor is invoked with an argument that provides the new value.

Die List<T>-Klasse deklariert die zwei Eigenschaften „Count“ und „Capacity“, von denen die eine schreibgeschützt ist und die andere Lese- und Schreibzugriff besitzt.The List<T> class declares two properties, Count and Capacity, which are read-only and read-write, respectively. Es folgt ein Beispiel zur Verwendung dieser Eigenschaften.The following is an example of use of these properties.

List<string> names = new List<string>();
names.Capacity = 100;   // Invokes set accessor
int i = names.Count;    // Invokes get accessor
int j = names.Capacity; // Invokes get accessor

Ähnlich wie bei Feldern und Methoden unterstützt C# sowohl Instanzeigenschaften als auch statische Eigenschaften.Similar to fields and methods, C# supports both instance properties and static properties. Statische Eigenschaften werden mit dem static-Modifizierer, Instanzeigenschaften werden ohne static-Modifizierer deklariert.Static properties are declared with the static modifier, and instance properties are declared without it.

Die Accessors einer Eigenschaft können virtuell sein.The accessor(s) of a property can be virtual. Wenn eine Eigenschaftendeklaration einen virtual-, abstract- oder override-Modifizierer enthält, wird dieser auf den Accessor der Eigenschaft angewendet.When a property declaration includes a virtual, abstract, or override modifier, it applies to the accessor(s) of the property.

IndexerIndexers

Ein Indexer ist ein Member, mit dem Objekte wie ein Array indiziert werden können.An indexer is a member that enables objects to be indexed in the same way as an array. Ein Indexer wird wie eine Eigenschaft deklariert, abgesehen davon, dass an den Membernamen eine in die Trennzeichen [ und ] eingefügte Parameterliste angehängt wird.An indexer is declared like a property except that the name of the member is this followed by a parameter list written between the delimiters [ and ]. Die Parameter stehen im Accessor des Indexers zur Verfügung.The parameters are available in the accessor(s) of the indexer. Ähnlich wie Eigenschaften können Indexer Lese-/Schreibzugriff besitzen, schreibgeschützt und lesegeschützt sein und virtuelle Accessors verwenden.Similar to properties, indexers can be read-write, read-only, and write-only, and the accessor(s) of an indexer can be virtual.

Die List-Klasse deklariert einen einzigen Indexer mit Lese-/Schreibzugriff, der einen int-Parameter akzeptiert.The List class declares a single read-write indexer that takes an int parameter. Der Indexer ermöglicht es, Instanzen von List mit int-Werten zu indizieren.The indexer makes it possible to index List instances with int values. Zum Beispiel:For example:

List<string> names = new List<string>();
names.Add("Liz");
names.Add("Martha");
names.Add("Beth");
for (int i = 0; i < names.Count; i++) 
{
    string s = names[i];
    names[i] = s.ToUpper();
}

Indexer können überladen werden, d.h. eine Klasse kann mehrere Indexer deklarieren, solange sich die Anzahl oder Typen ihrer Parameter unterscheiden.Indexers can be overloaded, meaning that a class can declare multiple indexers as long as the number or types of their parameters differ.

EreignisseEvents

Ein Ereignis ist ein Member, der es einer Klasse oder einem Objekt ermöglicht, Benachrichtigungen bereitzustellen.An event is a member that enables a class or object to provide notifications. Ein Ereignis wird wie ein Feld deklariert, abgesehen davon, dass es ein event-Schlüsselwort enthält und einen Delegattyp aufweisen muss.An event is declared like a field except that the declaration includes an event keyword and the type must be a delegate type.

Innerhalb einer Klasse, die einen Ereignismember deklariert, verhält sich das Ereignis wie ein Feld des Delegattyps (vorausgesetzt, das Ereignis ist nicht abstrakt und deklariert keine Accessors).Within a class that declares an event member, the event behaves just like a field of a delegate type (provided the event is not abstract and does not declare accessors). Das Feld speichert einen Verweis auf einen Delegaten, der die Ereignishandler repräsentiert, die dem Ereignis hinzugefügt wurden.The field stores a reference to a delegate that represents the event handlers that have been added to the event. Wenn keine Ereignishandler vorhanden sind, ist das Feld null.If no event handlers are present, the field is null.

Die List<T>-Klasse deklariert einen einzigen Ereignismember namens Changed, der angibt, dass der Liste ein neues Element hinzugefügt wurde.The List<T> class declares a single event member called Changed, which indicates that a new item has been added to the list. Das Changed-Ereignis wird durch die virtuelle Methode OnChanged ausgelöst, die zunächst prüft, ob das Ereignis null ist (d.h. nicht über Handler verfügt).The Changed event is raised by the OnChanged virtual method, which first checks whether the event is null (meaning that no handlers are present). Das Auslösen eines Ereignisses entspricht exakt dem Aufrufen des Delegaten, der durch das Ereignis repräsentiert wird, es gibt deshalb keine besonderen Sprachkonstrukte zum Auslösen von Ereignissen.The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events.

Clients reagieren über Ereignishandler auf Ereignisse.Clients react to events through event handlers. Ereignishandler werden unter Verwendung des +=-Operators angefügt und mit dem -=-Operator entfernt.Event handlers are attached using the += operator and removed using the -= operator. Im folgenden Beispiel wird dem Changed-Ereignis von List<string> ein Ereignishandler hinzugefügt.The following example attaches an event handler to the Changed event of a List<string>.

class EventExample
{
    static int changeCount;
    static void ListChanged(object sender, EventArgs e) 
    {
        changeCount++;
    }
    public static void Usage() 
    {
        List<string> names = new List<string>();
        names.Changed += new EventHandler(ListChanged);
        names.Add("Liz");
        names.Add("Martha");
        names.Add("Beth");
        Console.WriteLine(changeCount);		// Outputs "3"
    }
}

In komplexeren Szenarien, in denen die zugrunde liegende Speicherung eines Ereignisses gesteuert werden soll, können in einer Ereignisdeklaration explizit die add- und remove-Accessors bereitgestellt werden. Diese ähneln in gewisser Weise dem set-Accessor einer Eigenschaft.For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide add and remove accessors, which are somewhat similar to the set accessor of a property.

OperatorenOperators

Ein Operator ist ein Member, der die Bedeutung der Anwendung eines bestimmten Ausdrucksoperators auf Instanzen einer Klasse definiert.An operator is a member that defines the meaning of applying a particular expression operator to instances of a class. Es können drei Arten von Operatoren definiert werden: unäre Operatoren, binäre Operatoren und Konvertierungsoperatoren.Three kinds of operators can be defined: unary operators, binary operators, and conversion operators. Alle Operatoren müssen als public und static deklariert werden.All operators must be declared as public and static.

Die List<T>-Klasse deklariert zwei Operatoren, operator == und operator !=, und verleiht so Ausdrücken, die diese Operatoren auf List-Instanzen anwenden, eine neue Bedeutung.The List<T> class declares two operators, operator == and operator !=, and thus gives new meaning to expressions that apply those operators to List instances. Insbesondere die Operatoren definieren die Gleichheit für zwei Instanzen von List<T>, indem alle enthaltenen Objekte mithilfe ihrer Equals-Methoden verglichen werden.Specifically, the operators define equality of two List<T> instances as comparing each of the contained objects using their Equals methods. Im folgenden Beispiel wird der ==-Operator verwendet, um zwei Instanzen von List<int> zu vergleichen.The following example uses the == operator to compare two List<int> instances.

List<int> a = new List<int>();
a.Add(1);
a.Add(2);
List<int> b = new List<int>();
b.Add(1);
b.Add(2);
Console.WriteLine(a == b);  // Outputs "True" 
b.Add(3);
Console.WriteLine(a == b);  // Outputs "False"

Die erste Methode Console.WriteLine gibt True aus, weil die zwei Listen dieselbe Anzahl von Objekten mit denselben Werten in derselben Reihenfolge enthalten.The first Console.WriteLine outputs True because the two lists contain the same number of objects with the same values in the same order. Wenn List<T> nicht operator == definieren würde, würde die Ausgabe der ersten Console.WriteLine-Methode False lauten, weil a und b auf unterschiedliche List<int>-Instanzen verweisen.Had List<T> not defined operator ==, the first Console.WriteLine would have output False because a and b reference different List<int> instances.

FinalizerFinalizers

Ein Finalizer ist ein Member, der die erforderlichen Aktionen zum Bereinigen einer Instanz einer Klasse implementiert.A finalizer is a member that implements the actions required to finalize an instance of a class. Finalizer können weder Parameter noch Zugriffsmodifizierer aufweisen und können nicht explizit aufgerufen werden.Finalizers cannot have parameters, they cannot have accessibility modifiers, and they cannot be invoked explicitly. Der Finalizer für eine Instanz wird bei der Garbagecollection automatisch aufgerufen.The finalizer for an instance is invoked automatically during garbage collection.

Der Garbage Collector kann weitestgehend selbst über den Zeitpunkt der Objektbereinigung und die Ausführung der Finalizer entscheiden.The garbage collector is allowed wide latitude in deciding when to collect objects and run finalizers. Insbesondere der Zeitpunkt für den Aufruf der Finalizer ist nicht festgelegt, und Finalizer können für beliebige Threads ausgeführt werden.Specifically, the timing of finalizer invocations is not deterministic, and finalizers may be executed on any thread. Aus diesen und weiteren Gründen sollten Klassen Finalizer nur dann implementieren, wenn keine andere Lösung möglich ist.For these and other reasons, classes should implement finalizers only when no other solutions are feasible.

Die using-Anweisung bietet einen besseren Ansatz für die Objektzerstörung.The using statement provides a better approach to object destruction.