Condividi tramite


Istruzioni di dichiarazione

Un'istruzione di dichiarazione dichiara una nuova variabile locale, una costante locale o variabile di riferimento locale.

Il riferimento al linguaggio C# documenta la versione rilasciata più di recente del linguaggio C#. Contiene anche la documentazione iniziale per le funzionalità nelle anteprime pubbliche per la versione futura del linguaggio.

La documentazione identifica tutte le funzionalità introdotte nelle ultime tre versioni della lingua o nelle anteprime pubbliche correnti.

Suggerimento

Per trovare quando una funzionalità è stata introdotta per la prima volta in C#, vedere l'articolo sulla cronologia delle versioni del linguaggio C#.

Per dichiarare una variabile locale, specificarne il tipo e il nome. È possibile dichiarare più variabili dello stesso tipo in un'istruzione, come illustrato nell'esempio seguente:

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

In un'istruzione di dichiarazione è anche possibile inizializzare una variabile con il relativo valore iniziale:

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

Gli esempi precedenti specificano in modo esplicito il tipo di una variabile. È anche possibile consentire al compilatore di dedurre il tipo di una variabile dalla relativa espressione di inizializzazione. A tale scopo, usare la parola chiave var anziché il nome di un tipo. Per altre informazioni, vedere Variabili locali tipizzate in modo implicito.

Per dichiarare una costante locale, usare la parola chiave const, come illustrato nell'esempio seguente:

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

Quando si dichiara una costante locale, è anche necessario inizializzarla.

Per informazioni sulle variabili di riferimento locali, vedere la sezione Variabili di riferimento.

Variabili locali tipizzate in modo implicito

Quando si dichiara una variabile locale, è possibile consentire al compilatore di dedurre il tipo della variabile dall'espressione di inizializzazione. A tale scopo, usare la var parola chiave anziché il nome di un tipo:

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]

Come illustrato nell'esempio precedente, le variabili locali tipizzate in modo implicito sono fortemente tipizzate.

Nota

Quando si usa var nel contesto con riconoscimento nullable abilitato e il tipo di un'espressione di inizializzazione è un tipo riferimento, il compilatore deduce sempre un tipo riferimento nullable anche se il tipo di un'espressione di inizializzazione non è nullable.

La parola chiave var viene generalmente usata con un'espressione di chiamata di un costruttore. L'uso di consente di evitare di ripetere un nome di tipo in una dichiarazione di variabile e di creare un'istanza dell'oggetto var , come illustrato nell'esempio seguente:

var xs = new List<int>();

È possibile usare un'espressione new con tipo di destinazione come alternativa:

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

Quando si usano tipi anonimi, è necessario usare variabili locali tipizzate in modo implicito. L'esempio seguente mostra un'espressione di query che usa un tipo anonimo per contenere il nome e il numero di telefono di un cliente:

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

Nell'esempio precedente non è possibile specificare in modo esplicito il tipo della variabile fromPhoenix. Il tipo è IEnumerable<T> ma in questo caso T è un tipo anonimo e non è possibile specificarne il nome. Ecco perché è necessario usare var. Per lo stesso motivo, è necessario usare var quando si dichiara la variabile di iterazione customer nell'istruzione foreach.

Per altre informazioni sulle variabili locali tipizzate in modo implicito, vedere Variabili locali tipizzate in modo implicito.

Nella corrispondenza dei criteri, la parola chiave var viene usata in un criterio var.

Variabili di riferimento

Quando si dichiara una variabile locale e si aggiunge la parola chiave ref prima del tipo della variabile, si dichiara una variabile di riferimento o una variabile ref locale:

ref int aliasOfvariable = ref variable;

Una variabile di riferimento è una variabile che fa riferimento a un'altra variabile, denominata referente. Ovvero, una variabile di riferimento è un alias per il relativo referente. Quando si assegna un valore a una variabile di riferimento, si assegna tale valore al referenziale. Quando si legge il valore di una variabile di riferimento, si restituisce il valore del referenziale. L'esempio seguente illustra questo comportamento:

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)

Usare l'operatore di assegnazione ref= ref per modificare il referente di una variabile di riferimento, come illustrato nell'esempio seguente:

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

Nell'esempio precedente la variabile di riferimento element viene inizializzata come alias per il primo elemento della matrice. ref viene quindi riassegnata per fare riferimento all'ultimo elemento della matrice.

È possibile definire una variabile locale ref readonly. Non è possibile assegnare un valore a una variabile ref readonly. Tuttavia, è possibile ref riassegnare tale variabile di riferimento, come illustrato nell'esempio seguente:

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

È possibile assegnare un valore restituito di riferimento a una variabile di riferimento, come illustrato nell'esempio seguente:

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

Nell'esempio precedente il metodo GetReferenceToMax è un metodo returns-by-ref. Non restituisce il valore massimo stesso, ma un valore restituito di riferimento che è un alias dell'elemento della matrice che contiene il valore massimo. Il metodo Run assegna un valore restituito di riferimento alla variabile di riferimento max. Assegnando quindi a max, aggiorna lo spazio di archiviazione interno dell'istanza store. È anche possibile definire un metodo ref readonly. I chiamanti di un metodo ref readonly non possono assegnare un valore al valore restituito di riferimento.

La variabile di iterazione dell'istruzione foreach può essere una variabile di riferimento. Per altre informazioni, vedere la sezione relativa all'istruzione foreach dell'articolo Istruzioni di iterazione.

Negli scenari critici per le prestazioni, l'uso delle variabili di riferimento e dei valori restituiti potrebbe migliorare le prestazioni evitando operazioni di copia potenzialmente costose.

Il compilatore garantisce che una variabile di riferimento non sopravviva il suo referente e rimanga valida per l'intera durata. Per altre informazioni, vedere la sezione Contesti sicuri di riferimento della specifica del linguaggio C#.

Per informazioni sui campi ref, vedere la sezione campi ref dell'articolo tipi di strutture ref.

riferimento con ambito

La parola chiave contestuale scoped limita la durata di un valore. Il modificatore scoped limita rispettivamente la durata ref-safe-to-escape or safe-to-escape al metodo corrente. Aggiungendo il modificatore, si afferma che il scoped codice non estende la durata della variabile.

Applicare scoped a un parametro o a una variabile locale. È possibile applicare il scoped modificatore ai parametri e alle variabili locali quando il tipo è .ref struct In caso contrario, applicare il scoped modificatore solo alle variabili di riferimento locali. Tale regola include variabili locali dichiarate con il ref modificatore e i parametri dichiarati con i inmodificatori , refo out .

Il modificatore scoped viene aggiunto in modo implicito a this nei metodi dichiarati in struct, nei parametri out e nei parametri ref quando il tipo è ref struct.

Specifiche del linguaggio C#

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:

Per altre informazioni sul modificatore scoped, vedere la nota sulla proposta miglioramenti dello struct di basso livello.

Vedi anche