Deklarationsuttryck

En deklarationssats deklarerar en ny lokal variabel, lokal konstant eller lokal referensvariabel. Om du vill deklarera en lokal variabel anger du dess typ och anger dess namn. Du kan deklarera flera variabler av samma typ i en -instruktion, som följande exempel visar:

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

I en deklarationssats kan du också initiera en variabel med dess ursprungliga värde:

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

I föregående exempel anges uttryckligen typen av en variabel. Du kan också låta kompilatorn härleda typen av en variabel från dess initieringsuttryck. Det gör du genom att använda nyckelordet var i stället för en typs namn. Mer information finns i avsnittet Implicit skrivna lokala variabler .

Om du vill deklarera en lokal konstant använder du nyckelordetconst, som följande exempel visar:

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

När du deklarerar en lokal konstant måste du också initiera den.

Information om lokala referensvariabler finns i avsnittet Referensvariabler .

Implicit skrivna lokala variabler

När du deklarerar en lokal variabel kan du låta kompilatorn härleda typen av variabel från initieringsuttrycket. För att göra det använder du nyckelordet var i stället för namnet på en typ:

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]

Som föregående exempel visar skrivs implicit inskrivna lokala variabler starkt.

Kommentar

När du använder var i den aktiverade null-medvetna kontexten och typen av ett initieringsuttryck är en referenstyp, härleder kompilatorn alltid en nullbar referenstyp även om typen av ett initieringsuttryck inte är null.

En vanlig användning av var är med ett konstruktoranropsuttryck. Med hjälp av var kan du inte upprepa ett typnamn i en variabeldeklaration och objekt-instansiering, vilket visas i följande exempel:

var xs = new List<int>();

Du kan använda ett måltypat new uttryck som ett alternativ:

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

När du arbetar med anonyma typer måste du använda implicit skrivna lokala variabler. I följande exempel visas ett frågeuttryck som använder en anonym typ för att lagra en kunds namn och telefonnummer:

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}");
}

I föregående exempel kan du inte uttryckligen ange typen av fromPhoenix variabel. Typen är IEnumerable<T> men i det här fallet T är en anonym typ och du kan inte ange dess namn. Det är därför du måste använda var. Av samma anledning måste du använda var när du deklarerar customer iterationsvariabeln i -instruktionen foreach .

Mer information om implicit inskrivna lokala variabler finns i Implicit skrivna lokala variabler.

I mönstermatchning används nyckelordet var i ett var mönster.

Referensvariabler

När du deklarerar en lokal variabel och lägger till nyckelordet ref före variabelns typ deklarerar du en referensvariabel eller en ref lokal:

ref int aliasOfvariable = ref variable;

En referensvariabel är en variabel som refererar till en annan variabel, som kallas referens. En referensvariabel är alltså ett alias för dess referens. När du tilldelar ett värde till en referensvariabel tilldelas det värdet till referensen. När du läser värdet för en referensvariabel returneras referensvärdet. Följande exempel visar det beteendet:

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

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

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

Använd tilldelningsoperatorn ref = ref för att ändra referensen för en referensvariabel, som följande exempel visar:

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

I föregående exempel element initieras referensvariabeln som ett alias för det första matriselementet. Sedan tilldelas ref den om för att referera till det sista matriselementet.

Du kan definiera en ref readonly lokal variabel. Du kan inte tilldela ett värde till en ref readonly variabel. Du kan ref dock tilldela om en sådan referensvariabel, vilket visas i följande exempel:

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

Du kan tilldela en referensretur till en referensvariabel, som följande exempel visar:

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
    }
}

I föregående exempel GetReferenceToMax är metoden en metoden returns-by-ref . Det returnerar inte det maximala värdet självt, men en referensretur som är ett alias till matriselementet som innehåller det maximala värdet. Metoden Run tilldelar en referensretur till max referensvariabeln. Genom att tilldela till maxuppdaterar den sedan den interna lagringen för instansen store . Du kan också definiera en ref readonly metod. Anroparna för en ref readonly metod kan inte tilldela ett värde till referensreturen.

Iterationsvariabeln för -instruktionen foreach kan vara en referensvariabel. Mer information finns i instruktionsavsnittet foreach i artikeln Iteration-instruktioner.

I prestandakritiska scenarier kan användningen av referensvariabler och returer öka prestandan genom att undvika potentiellt dyra kopieringsåtgärder.

Kompilatorn ser till att en referensvariabel inte överlever sina referenser och förblir giltig under hela sin livslängd. Mer information finns i avsnittet Referenssäkra kontexter i C#-språkspecifikationen.

Information om fälten ref finns i ref avsnittet fält i ref artikeln strukturtyper .

begränsad referens

Det kontextuella nyckelordet scoped begränsar livslängden för ett värde. Modifieraren scoped begränsar livslängden ref-safe-to-escape eller safe-to-escape till den aktuella metoden. Genom att lägga till scoped modifieraren kan du se till att koden inte förlänger variabelns livslängd.

Du kan använda scoped för en parameter eller lokal variabel. Modifieraren scoped kan tillämpas på parametrar och lokalbefolkningen när typen är en ref struct. I annat fall scoped kan modifieraren endast tillämpas på lokala referensvariabler. Det inkluderar lokala variabler som deklarerats med ref modifieraren och parametrarna som deklarerats med in, ref eller out modifierare.

Modifieraren scoped läggs implicit till this i i metoder som deklareras i parametrarna struct, out och ref när typen är en ref struct.

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Mer information om scoped modifieraren finns i förslaget om förbättringar på låg nivå.

Se även