Deklarationsanweisungen

Eine Deklarationsanweisung deklariert eine neue lokale Variable, eine lokale Konstante oder eine lokale Verweisvariable. Um eine lokale Variable zu deklarieren, geben Sie ihren Typ und ihren Namen an. Sie können mehrere Variablen desselben Typs in einer Anweisung deklarieren, wie das folgende Beispiel zeigt:

string greeting;
int a, b, c;
List<double> xs;

Sie können eine Variable in einer Deklarationsanweisung auch mit einem Anfangswert initialisieren:

string greeting = "Hello";
int a = 3, b = 2, c = a + b;
List<double> xs = new();

In den vorherigen Beispielen wurde der Typ der Variablen explizit angegeben. Sie können den Datentyp einer Variable auch durch den Compiler vom Typ des Initialisierungsausdrucks ableiten lassen. Verwenden Sie dazu das Schlüsselwort var anstelle des Namens eines Typs. Weitere Informationen finden Sie im Abschnitt Implizit typisierte lokale Variablen.

Um eine lokale Konstante zu deklarieren, verwenden Sie das Schlüsselwort const, wie im folgenden Beispiel gezeigt:

const string Greeting = "Hello";
const double MinLimit = -10.0, MaxLimit = -MinLimit;

Wenn Sie eine lokale Konstante deklarieren, müssen Sie diese auch initialisieren.

Informationen zu lokalen Verweisvariablen finden Sie im Abschnitt Verweisvariablen.

Implizit typisierte lokale Variablen

Wenn Sie eine lokale Variable deklarieren, können Sie den Typ der Variable durch den Compiler aus dem Initialisierungsausdruck ableiten lassen. Verwenden Sie dazu das Schlüsselwort var anstelle des Namens eines Typs:

var greeting = "Hello";
Console.WriteLine(greeting.GetType());  // output: System.String

var a = 32;
Console.WriteLine(a.GetType());  // output: System.Int32

var xs = new List<double>();
Console.WriteLine(xs.GetType());  // output: System.Collections.Generic.List`1[System.Double]

Wie das vorherige Beispiel zeigt, werden implizit typisierte lokale Variablen stark typisiert.

Hinweis

Wenn Sie var im aktivierten Nullwerte zulassenden Kontext verwenden und der Typ eines Initialisierungsausdrucks ein Verweistyp ist, leitet der Compiler immer einen Nullwerte zulassenden Verweistyp ab, auch wenn der Typ eines Initialisierungsausdrucks keine Nullwerte zulässt.

var wird häufig zusammen mit einem Ausdruck mit einem Konstruktoraufruf verwendet. Durch die Verwendung von var können Sie einen Typnamen in einer Variablendeklaration und Objektinstanziierung nicht wiederholen, wie im folgenden Beispiel gezeigt:

var xs = new List<int>();

Sie können als Alternative einen als Ziel typisierten new-Ausdruck verwenden:

List<int> xs = new();
List<int>? ys = new();

Wenn Sie mit anonyme Typen arbeiten, müssen Sie implizit typisierte lokale Variablen verwenden. Das folgende Beispiel zeigt einen Abfrageausdruck, der einen anonymen Typ verwendet, um den Namen und die Telefonnummer von Kund*innen zu speichern:

var fromPhoenix = from cust in customers
                  where cust.City == "Phoenix"
                  select new { cust.Name, cust.Phone };

foreach (var customer in fromPhoenix)
{
    Console.WriteLine($"Name={customer.Name}, Phone={customer.Phone}");
}

Im vorherigen Beispiel können Sie den Typ der Variable fromPhoenix nicht explizit angeben. Der Typ ist IEnumerable<T>, aber in diesem Fall ist T ein anonymer Typ, dessen Namen Sie nicht angeben können. Aus diesem Grund müssen Sie var verwenden. Aus demselben Grund müssen Sie var verwenden, wenn Sie die Iterationsvariable customer in der foreach-Anweisung deklarieren.

Weitere Informationen zu implizit typisierten lokalen Variablen finden Sie unter Implizit typisierte lokale Variablen.

Bei einem Musterabgleich wird das var-Schlüsselwort in einem var-Muster verwendet.

Verweisvariablen

Wenn Sie eine lokale Variable deklarieren und das ref-Schlüsselwort vor dem Typ der Variablen hinzufügen, deklarieren Sie eine Verweisvariable oder eine „ref local“:

ref int alias = ref variable;

Eine Verweisvariable ist eine Variable, die auf eine andere Variable verweist, die als Referent bezeichnet wird. Das heißt, eine Verweisvariable ist ein Alias für ihren Referenten. Wenn Sie einer Verweisvariablen einen Wert zuweisen, wird dieser Wert dem Referenten zugewiesen. Wenn Sie den Wert einer Verweisvariablen lesen, wird der Wert des Referenten zurückgegeben. Das folgende Beispiel veranschaulicht dieses Verhalten:

int a = 1;
ref int alias = ref a;
Console.WriteLine($"(a, alias) is ({a}, {alias})");  // output: (a, alias) is (1, 1)

a = 2;
Console.WriteLine($"(a, alias) is ({a}, {alias})");  // output: (a, alias) is (2, 2)

alias = 3;
Console.WriteLine($"(a, alias) is ({a}, {alias})");  // output: (a, alias) is (3, 3)

Verwenden Sie den ref-Zuweisungsoperator= ref, um den Referenten einer Verweisvariablen zu ändern, wie das folgende Beispiel zeigt:

void Display(int[] s) => Console.WriteLine(string.Join(" ", s));

int[] xs = [0, 0, 0];
Display(xs);

ref int element = ref xs[0];
element = 1;
Display(xs);

element = ref xs[^1];
element = 3;
Display(xs);
// Output:
// 0 0 0
// 1 0 0
// 1 0 3

Im vorstehenden Beispiel wird die element-Verweisvariable als Alias für das erste Arrayelement initialisiert. Anschließend wird ihr ref erneut zugewiesen, um auf das letzte Arrayelement zu verweisen.

Sie können eine lokale ref readonly-Variable definieren. Sie können einer ref readonly-Variablen keinen Wert zuweisen. Sie können jedoch ref eine solche Verweisvariable neu zuweisen, wie das folgende Beispiel zeigt:

int[] xs = [1, 2, 3];

ref readonly int element = ref xs[0];
// element = 100;  error CS0131: The left-hand side of an assignment must be a variable, property or indexer
Console.WriteLine(element);  // output: 1

element = ref xs[^1];
Console.WriteLine(element);  // output: 3

Sie können einer Verweisvariablen eine Verweisrückgabe zuweisen, wie das folgende Beispiel zeigt:

using System;

public class NumberStore
{
    private readonly int[] numbers = [1, 30, 7, 1557, 381, 63, 1027, 2550, 511, 1023];

    public ref int GetReferenceToMax()
    {
        ref int max = ref numbers[0];
        for (int i = 1; i < numbers.Length; i++)
        {
            if (numbers[i] > max)
            {
                max = ref numbers[i];
            }
        }
        return ref max;
    }

    public override string ToString() => string.Join(" ", numbers);
}

public static class ReferenceReturnExample
{
    public static void Run()
    {
        var store = new NumberStore();
        Console.WriteLine($"Original sequence: {store.ToString()}");
        
        ref int max = ref store.GetReferenceToMax();
        max = 0;
        Console.WriteLine($"Updated sequence:  {store.ToString()}");
        // Output:
        // Original sequence: 1 30 7 1557 381 63 1027 2550 511 1023
        // Updated sequence:  1 30 7 1557 381 63 1027 0 511 1023
    }
}

Im vorherigen Beispiel ist die GetReferenceToMax-Methode eine returns-by-ref-Methode. Sie gibt nicht den maximalen Wert selbst zurück, sondern eine Verweisrückgabe, die ein Alias für das Arrayelement ist, das den maximalen Wert enthält. Die Run-Methode weist der max-Verweisvariablen eine Verweisrückgabe zu. Durch Zuweisen zu max aktualisiert sie dann den internen Speicher der store-Instanz. Sie können auch eine ref readonly-Methode definieren. Die Aufrufer einer ref readonly-Methode können ihrer Verweisrückgabe keinen Wert zuweisen.

Die Iterationsvariable der foreach-Anweisung kann eine Verweisvariable sein. Weitere Informationen finden Sie im Abschnitt foreach-Anweisung im Artikel Iterationsanweisungen.

In leistungskritischen Szenarien kann die Verwendung von Verweisvariablen und Rückgaben die Leistung steigern, indem potenziell teure Kopiervorgänge vermieden werden.

Der Compiler stellt sicher, dass eine Verweisvariable ihren Referenten nicht überdauert und für die gesamte Lebensdauer gültig bleibt. Weitere Informationen finden Sie im Abschnitt Ref-safe-Kontexte der C#-Sprachspezifikation.

Informationen zu den ref-Feldern finden Sie im Abschnitt ref-Felder des Artikels ref-Strukturtypen.

Bereichsbezogene „ref“-Variable

Das kontextbezogene Schlüsselwort scoped schränkt die Lebensdauer eines Werts ein. Der Modifizierer scoped beschränkt die ref-safe-to-escape- bzw safe-to-escape-Lebensdauer auf die aktuelle Methode. Durch das Hinzufügen des Modifikators scoped wird sichergestellt, dass Ihr Code die Lebensdauer der Variablen nicht verlängert.

Sie können scoped auf einen Parameter oder eine lokale Variable anwenden. Der Modifizierer scoped kann auf Parameter und lokale Variablen angewendet werden, wenn der Typ ein ref struct ist. Andernfalls kann der Modifizierer scoped nur auf lokale Verweisvariablen angewendet werden. Dies umfasst lokale Variablen, die mit dem Modifizierer ref deklariert wurden, und Parameter, die mit dem Modifizierer in, ref oder out deklariert wurden.

Der scoped-Modifizierer wird implizit zu this in Methoden hinzugefügt, die in einem struct- bzw. out-Parameter und einem ref-Parameter deklariert sind, wenn der Typ ein ref struct ist.

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Weitere Informationen zum Modifizierer scoped finden Sie im Vorschlag zu Strukturverbesserungen auf niedriger Ebene.

Weitere Informationen