ref (Riferimenti per C#)ref (C# Reference)

La parola chiave ref indica un valore che viene passato per riferimento.The ref keyword indicates a value that is passed by reference. Viene usata in quattro contesti diversi:It is used in four different contexts:

  • Nella firma di un metodo e in una chiamata al metodo, per passare un argomento a un metodo per riferimento.In a method signature and in a method call, to pass an argument to a method by reference. Per altre informazioni, vedere Passaggio di un argomento per riferimento.For more information, see Passing an argument by reference.
  • Nella firma di un metodo, per restituire un valore al chiamante per riferimento.In a method signature, to return a value to the caller by reference. Per altre informazioni, vedere Valori di riferimento restituiti.For more information, see Reference return values.
  • Nel corpo di un membro, per indicare che un valore restituito di riferimento è archiviato in locale come un riferimento che il chiamante intende modificare o, in generale, che una variabile locale accede a un altro valore per riferimento.In a member body, to indicate that a reference return value is stored locally as a reference that the caller intends to modify or, in general, a local variable accesses another value by reference. Per altre informazioni, vedere Variabili locali ref.For more information, see Ref locals.
  • In una dichiarazione struct per dichiarare ref struct o readonly ref struct.In a struct declaration to declare a ref struct or a readonly ref struct. Per altre informazioni, vedere Tipi ref struct.For more information, see ref struct types.

Passaggio di un argomento per riferimentoPassing an argument by reference

Quando viene usata nell'elenco di parametri di un metodo, la parola chiave ref indica che un argomento viene passato per riferimento, non per valore.When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. La parola chiave ref imposta il parametro formale come alias dell'argomento, che deve essere una variabile.The ref keyword makes the formal parameter an alias for the argument, which must be a variable. In altre parole, qualsiasi operazione sul parametro viene eseguita sull'argomento.In other words, any operation on the parameter is made on the argument. Ad esempio, se il chiamante passa un'espressione variabile locale o un'espressione di accesso dell'elemento della matrice e il metodo chiamato sostituisce l'oggetto a cui fa riferimento il parametro ref, l'elemento della matrice o la variabile locale del chiamante fa riferimento al nuovo oggetto quando viene restituito il risultato del metodo.For example, if the caller passes a local variable expression or an array element access expression, and the called method replaces the object to which the ref parameter refers, then the caller’s local variable or the array element now refers to the new object when the method returns.

Nota

Non confondere il concetto di passaggio per riferimento con il concetto di tipi di riferimento.Do not confuse the concept of passing by reference with the concept of reference types. I due concetti non sono uguali.The two concepts are not the same. Un parametro di metodo può essere modificato da ref che si tratti di un tipo di valore o di un tipo di riferimento.A method parameter can be modified by ref regardless of whether it is a value type or a reference type. Non viene eseguito il boxing di un tipo di valore quando viene passato per riferimento.There is no boxing of a value type when it is passed by reference.

Per usare un parametro ref, la definizione del metodo e il metodo chiamante devono usare in modo esplicito la parola chiave ref, come illustrato nell'esempio seguente.To use a ref parameter, both the method definition and the calling method must explicitly use the ref keyword, as shown in the following example.

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45

Un argomento passato a un parametro ref o in deve essere inizializzato prima di essere passato.An argument that is passed to a ref or in parameter must be initialized before it is passed. Questo comportamento è diverso dai parametri out, i cui argomenti non devono essere inizializzati in modo esplicito prima di essere passati.This differs from out parameters, whose arguments do not have to be explicitly initialized before they are passed.

I membri di una classe non possono avere firme che differiscono solo per ref, in o out.Members of a class can't have signatures that differ only by ref, in, or out. Un errore del compilatore si verifica se l'unica differenza tra due membri di un tipo è che uno di essi ha un parametro ref e l'altro ha un parametro out o in.A compiler error occurs if the only difference between two members of a type is that one of them has a ref parameter and the other has an out, or in parameter. Il codice seguente, ad esempio, non viene compilato.The following code, for example, doesn't compile.

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

È tuttavia possibile eseguire l'overload dei metodi quando un metodo ha un parametro ref, in o out e l'altro ha un parametro di valore, come illustrato nell'esempio seguente.However, methods can be overloaded when one method has a ref, in, or out parameter and the other has a value parameter, as shown in the following example.

class RefOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(ref int i) { }
}

In altre situazioni che richiedono la firma corrispondente, ad esempio nascondere o sottoporre a override, in, ref e out fanno parte della firma e non sono corrispondenti tra loro.In other situations that require signature matching, such as hiding or overriding, in, ref, and out are part of the signature and don't match each other.

Le proprietà non sono variabili.Properties are not variables. Sono metodi e non possono essere passate ai parametri ref.They are methods, and cannot be passed to ref parameters.

Non è possibile usare le parole chiave ref, in e out per i seguenti tipi di metodi:You can't use the ref, in, and out keywords for the following kinds of methods:

  • Metodi asincroni definiti usando il modificatore async.Async methods, which you define by using the async modifier.
  • Metodi iteratori che includono un'istruzione yield return o yield break.Iterator methods, which include a yield return or yield break statement.

Passaggio di un argomento per riferimento: un esempioPassing an argument by reference: An example

Negli esempi precedenti vengono passati tipi valore per riferimento.The previous examples pass value types by reference. È anche possibile usare la parola chiave ref per passare tipi riferimento per riferimento.You can also use the ref keyword to pass reference types by reference. Il passaggio di un tipo riferimento per riferimento consente al metodo chiamato di sostituire l'oggetto a cui fa riferimento il parametro per riferimento nel chiamante.Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller. Il percorso di archiviazione dell'oggetto viene passato al metodo come valore del parametro referenziato.The storage location of the object is passed to the method as the value of the reference parameter. Se si modifica il valore nella posizione di archiviazione del parametro (in modo che punti a un nuovo oggetto), è anche possibile modificare il percorso di archiviazione a cui fa riferimento il chiamante.If you change the value in the storage location of the parameter (to point to a new object), you also change the storage location to which the caller refers. Nell'esempio seguente viene passata un'istanza di un tipo di riferimento come parametro ref.The following example passes an instance of a reference type as a ref parameter.

class Product
{
    public Product(string name, int newID)
    {
        ItemName = name;
        ItemID = newID;
    }

    public string ItemName { get; set; }
    public int ItemID { get; set; }
}

private static void ChangeByReference(ref Product itemRef)
{
    // Change the address that is stored in the itemRef parameter.   
    itemRef = new Product("Stapler", 99999);

    // You can change the value of one of the properties of
    // itemRef. The change happens to item in Main as well.
    itemRef.ItemID = 12345;
}

private static void ModifyProductsByReference()
{
    // Declare an instance of Product and display its initial values.
    Product item = new Product("Fasteners", 54321);
    System.Console.WriteLine("Original values in Main.  Name: {0}, ID: {1}\n",
        item.ItemName, item.ItemID);

    // Pass the product instance to ChangeByReference.
    ChangeByReference(ref item);
    System.Console.WriteLine("Back in Main.  Name: {0}, ID: {1}\n",
        item.ItemName, item.ItemID);
}

// This method displays the following output:
// Original values in Main.  Name: Fasteners, ID: 54321
// Back in Main.  Name: Stapler, ID: 12345        

Per altre informazioni su come passare i tipi di riferimento per valore e per riferimento, vedere Passaggio di parametri di tipi di riferimento.For more information about how to pass reference types by value and by reference, see Passing Reference-Type Parameters.

Valori restituiti di riferimentoReference return values

I valori restituiti di riferimento (o valori restituiti ref) sono i valori che un metodo restituisce per riferimento al chiamante.Reference return values (or ref returns) are values that a method returns by reference to the caller. In altre parole, il chiamante può modificare il valore restituito da un metodo e tale modifica viene riflessa nello stato dell'oggetto che contiene il metodo.That is, the caller can modify the value returned by a method, and that change is reflected in the state of the object that contains the method.

Un valore restituito di riferimento viene definito mediante la parola chiave ref:A reference return value is defined by using the ref keyword:

  • Nella firma del metodo.In the method signature. Ad esempio, la firma del metodo seguente indica che il metodo GetCurrentPrice restituisce un valore Decimal per riferimento.For example, the following method signature indicates that the GetCurrentPrice method returns a Decimal value by reference.
public ref decimal GetCurrentPrice()
  • Tra il token return e la variabile restituita in un'istruzione return nel metodo.Between the return token and the variable returned in a return statement in the method. Ad esempio:For example:
return ref DecimalArray[0];

Affinché il chiamante modifichi lo stato dell'oggetto, il valore restituito di riferimento deve essere archiviato in una variabile definita in modo esplicito come variabile locale ref.In order for the caller to modify the object's state, the reference return value must be stored to a variable that is explicitly defined as a ref local.

Il metodo chiamato può anche dichiarare il valore restituito come ref readonly per restituire il valore per riferimento e specificare che il codice chiamante non può modificare il valore restituito.The called method may also declare the return value as ref readonly to return the value by reference, and enforce that the calling code cannot modify the returned value. Il metodo chiamante può evitare la copia del valore restituito archiviando il valore in una variabile ref readonly locale.The calling method can avoid copying the returned valued by storing the value in a local ref readonly variable.

Per un esempio, vedere Esempio di valori restituiti e variabili locali ref.For an example, see A ref returns and ref locals example.

Variabili locali refRef locals

Una variabile locale ref viene usata per fare riferimento ai valori restituiti mediante return ref.A ref local variable is used to refer to values returned using return ref. Non è possibile inizializzare una variabile locale ref in un valore restituito non ref.A ref local variable cannot be initialized to a non-ref return value. In altre parole, il lato destro dell'inizializzazione deve essere un riferimento.In other words, the right hand side of the initialization must be a reference. Tutte le modifiche apportate al valore della variabile locale ref vengono riflesse nello stato dell'oggetto di cui metodo ha restituito il valore per riferimento.Any modifications to the value of the ref local are reflected in the state of the object whose method returned the value by reference.

Per definire una variabile locale ref, usare la parola chiave ref prima della dichiarazione di variabile, nonché immediatamente prima della chiamata al metodo che restituisce il valore per riferimento.You define a ref local by using the ref keyword before the variable declaration, as well as immediately before the call to the method that returns the value by reference.

Ad esempio, l'istruzione seguente definisce un valore di variabile locale ref restituito da un metodo denominato GetEstimatedValue:For example, the following statement defines a ref local value that is returned by a method named GetEstimatedValue:

ref decimal estValue = ref Building.GetEstimatedValue();

È possibile accedere a un valore per riferimento nello stesso modo.You can access a value by reference in the same way. In alcuni casi, l'accesso a un valore per riferimento migliora le prestazioni evitando un'operazione di copia potenzialmente dispendiosa.In some cases, accessing a value by reference increases performance by avoiding a potentially expensive copy operation. L'istruzione seguente, ad esempio, spiega come sia possibile definire un valore locale di riferimento usato per fare riferimento a un valore.For example, the following statement shows how one can define a ref local value that is used to reference a value.

ref VeryLargeStruct reflocal = ref veryLargeStruct;

Si noti che nei due esempi la parola chiave ref deve essere usata in entrambe le posizioni. In caso contrario, il compilatore genera l'errore CS8172, "Non è possibile inizializzare una variabile per riferimento con un valore".Note that in both examples the ref keyword must be used in both places, or the compiler generates error CS8172, "Cannot initialize a by-reference variable with a value."

A partire da C# 7.3, la variabile di iterazione dell'istruzione foreach può essere una variabile locale ref o locale ref readonly.Beginning with C# 7.3, the iteration variable of the foreach statement can be ref local or ref readonly local variable. Per altre informazioni, vedere l'articolo sull'istruzione foreach.For more information, see the foreach statement article.

Variabili ref readonlyRef readonly locals

Una variabile locale ref readonly viene usata per fare riferimento ai valori restituiti dal metodo o dalla proprietà che include ref readonly nella propria firma e usa return ref.A ref readonly local is used to refer to values returned by the method or property that has ref readonly in its signature and uses return ref. Una variabile ref readonly combina le proprietà di una variabile locale ref con una variabile readonly: è un alias per l'archiviazione cui è assegnata e non può essere modificata.A ref readonly variable combines the properties of a ref local variable with a readonly variable: it is an alias to the storage it's assigned to, and it cannot be modified.

Esempio di valori restituiti e variabili locali refA ref returns and ref locals example

Nell'esempio seguente viene definita una classe Book che ha due campi String, Title e Author.The following example defines a Book class that has two String fields, Title and Author. Definisce inoltre una classe BookCollection che include una matrice privata di oggetti Book.It also defines a BookCollection class that includes a private array of Book objects. I singoli oggetti book vengono restituiti per riferimento chiamando il relativo metodo GetBookByTitle.Individual book objects are returned by reference by calling its GetBookByTitle method.


public class Book
{
    public string Author;
    public string Title;
}

public class BookCollection
{
    private Book[] books = { new Book { Title = "Call of the Wild, The", Author = "Jack London" },
                        new Book { Title = "Tale of Two Cities, A", Author = "Charles Dickens" }
                       };
    private Book nobook = null;

    public ref Book GetBookByTitle(string title)
    {
        for (int ctr = 0; ctr < books.Length; ctr++)
        {
            if (title == books[ctr].Title)
                return ref books[ctr];
        }
        return ref nobook;
    }

    public void ListBooks()
    {
        foreach (var book in books)
        {
            Console.WriteLine($"{book.Title}, by {book.Author}");
        }
        Console.WriteLine();
    }
}

Quando il chiamante archivia il valore restituito dal metodo GetBookByTitle come una variabile locale ref, le modifiche apportate al valore restituito dal chiamante vengono riflesse nell'oggetto BookCollection, come illustrato nell'esempio seguente.When the caller stores the value returned by the GetBookByTitle method as a ref local, changes that the caller makes to the return value are reflected in the BookCollection object, as the following example shows.

var bc = new BookCollection();
bc.ListBooks();

ref var book = ref bc.GetBookByTitle("Call of the Wild, The");
if (book != null)
    book = new Book { Title = "Republic, The", Author = "Plato" };
bc.ListBooks();
// The example displays the following output:
//       Call of the Wild, The, by Jack London
//       Tale of Two Cities, A, by Charles Dickens
//       
//       Republic, The, by Plato
//       Tale of Two Cities, A, by Charles Dickens

Tipi ref structRef struct types

L'aggiunta del modificatore ref a una dichiarazione struct specifica che le istanze di questo tipo devono essere allocate nello stack.Adding the ref modifier to a struct declaration defines that instances of that type must be stack allocated. In altre parole, questi tipi non possono mai essere creati nell'heap come membro di un'altra classe.In other words, instances of these types can never be created on the heap as a member of another class. La principale motivazione di questa funzionalità sono stati Span<T> e le strutture correlate.The primary motivation for this feature was Span<T> and related structures.

L'obiettivo di mantenere un tipo ref struct come variabile allocata nello stack comporta diverse regole che il compilatore applica per tutti i tipi ref struct.The goal of keeping a ref struct type as a stack-allocated variable introduces several rules that the compiler enforces for all ref struct types.

  • Non è possibile eseguire il boxing di ref struct.You can't box a ref struct. Non è possibile assegnare un tipo ref struct a una variabile di tipo object, dynamic o qualsiasi tipo di interfaccia.You cannot assign a ref struct type to a variable of type object, dynamic, or any interface type.
  • I tipi ref struct non possono implementare interfacce.ref struct types cannot implement interfaces.
  • Non è possibile dichiarare ref struct come campo membro di una classe o di un normale struct.You can't declare a ref struct as a field member of a class or a normal struct. Questo include la dichiarazione di una proprietà implementata automaticamente, che crea un campo sottostante generato dal compilatore.This includes declaring an auto-implemented property, which creates a compiler generated backing field.
  • Non è possibile dichiarare variabili locali che sono tipi ref struct nei metodi asincroni.You cannot declare local variables that are ref struct types in async methods. È possibile dichiararle nei metodi sincroni che restituiscono tipi simili a Task, Task<TResult> o Task.You can declare them in synchronous methods that return Task, Task<TResult> or Task-like types.
  • Non è possibile dichiarare variabili locali ref struct negli iteratori.You cannot declare ref struct local variables in iterators.
  • Non è possibile acquisire variabili ref struct in espressioni lambda o funzioni locali.You cannot capture ref struct variables in lambda expressions or local functions.

Queste restrizioni evitano l'uso accidentale di un tipo ref struct in modo che possa essere alzato di livello nell'heap gestito.These restrictions ensure you don't accidentally use a ref struct in a manner that could promote it to the managed heap.

È possibile combinare i modificatori per dichiarare uno struct come readonly ref.You can combine modifiers to declare a struct as readonly ref. readonly ref struct combina i vantaggi e le restrizioni delle dichiarazioni ref struct e readonly struct.A readonly ref struct combines the benefits and restrictions of ref struct and readonly struct declarations.

Specifiche del linguaggio C#C# language specification

Per altre informazioni, vedere la specifica del linguaggio C#.For more information, see the C# Language Specification. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.The language specification is the definitive source for C# syntax and usage.

Vedere ancheSee also