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

La ref parola chiave indica che un valore viene passato per riferimento.The ref keyword indicates that a value 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.In a member body, to indicate that a reference return value is stored locally as a reference that the caller intends to modify. O per indicare che una variabile locale accede a un altro valore per riferimento.Or to indicate that a local variable accesses another value by reference. Per altre informazioni, vedere Variabili locali ref.For more information, see Ref locals.
  • In una struct dichiarazione, per dichiarare un oggetto ref struct o un oggetto readonly ref struct .In a struct declaration, to declare a ref struct or a readonly ref struct. Per altre informazioni, vedere la sezione ref struct dell'articolo tipi di struttura .For more information, see the ref struct section of the Structure types article.

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.

Si supponga, ad esempio, che il chiamante passi un'espressione di variabile locale o un'espressione di accesso dell'elemento della matrice.For example, suppose the caller passes a local variable expression or an array element access expression. Il metodo chiamato può quindi sostituire l'oggetto a cui fa riferimento il parametro ref.The called method can then replace the object to which the ref parameter refers. In tal caso, la variabile locale del chiamante o l'elemento di matrice si riferisce al nuovo oggetto quando il metodo restituisce.In that case, the caller's local variable or the array element 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.Don't 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. Ad eccezione del fatto che il metodo chiamante può omettere ref quando si effettua una chiamata com.(Except that the calling method can omit ref when making a COM call.)

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 requisito è diverso dai parametri out , i cui argomenti non devono essere inizializzati in modo esplicito prima di essere passati.This requirement differs from out parameters, whose arguments don't 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 ref un in parametro, o out e l'altro ha un parametro passato per 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 parameter that is passed by value, 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. Si tratta di metodi e non possono essere passati ai ref parametri.They're 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.

i metodi di estensione presentano anche restrizioni sull'uso delle parole chiave seguenti:extension methods also have restrictions on the use of these keywords:

  • outNon è possibile usare la parola chiave sul primo argomento di un metodo di estensione.The out keyword cannot be used on the first argument of an extension method.
  • Non ref è possibile usare la parola chiave sul primo argomento di un metodo di estensione quando l'argomento non è uno struct oppure un tipo generico non vincolato come uno struct.The ref keyword cannot be used on the first argument of an extension method when the argument is not a struct, or a generic type not constrained to be a struct.
  • inNon è possibile usare la parola chiave a meno che il primo argomento non sia uno struct.The in keyword cannot be used unless the first argument is a struct. La in parola chiave non può essere usata in alcun tipo generico, anche quando è vincolato a essere uno struct.The in keyword cannot be used on any generic type, even when constrained to be a struct.

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. Ovvero il chiamante può modificare il valore restituito da un metodo e tale modifica viene riflessa nello stato dell'oggetto nel metodo chiamante.That is, the caller can modify the value returned by a method, and that change is reflected in the state of the object in the calling 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.

Di seguito è riportato un esempio di Return Ref più completo che mostra sia la firma del metodo che il corpo del metodo.Here's a more complete ref return example, showing both the method signature and method body.

public static ref int Find(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return ref matrix[i, j];
    throw new InvalidOperationException("Not found");
}

Il metodo chiamato può anche dichiarare il valore restituito come ref readonly per restituire il valore per riferimento e applicare 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 can't modify the returned value. Il metodo chiamante può evitare di copiare il valore restituito archiviando il valore in una variabile locale ref ReadOnly .The calling method can avoid copying the returned value by storing the value in a local ref readonly variable.

Per un esempio, vedere un esempio Ref Returns e Ref locals.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.

Si definisce un oggetto locale Ref usando la ref parola chiave in due posizioni:You define a ref local by using the ref keyword in two places:

  • Prima della dichiarazione di variabile.Before the variable declaration.
  • Immediatamente prima della chiamata al metodo che restituisce il valore per riferimento.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. Nell'istruzione seguente, ad esempio, viene illustrato come definire una variabile locale Ref utilizzata per fare riferimento a un valore.For example, the following statement shows how to define a ref local variable that is used to reference a value.

ref VeryLargeStruct reflocal = ref veryLargeStruct;

In entrambi gli esempi la ref parola chiave deve essere usata in entrambe le posizioni o il compilatore genera l'errore CS8172 "non è possibile inizializzare una variabile per riferimento con un valore".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' foreach istruzione può essere una variabile locale Ref local o ref ReadOnly.Beginning with C# 7.3, the iteration variable of the foreach statement can be a ref local or ref readonly local variable. Per altre informazioni, vedere l'articolo sull'istruzione foreach.For more information, see the foreach statement article.

Inoltre, a partire da C# 7,3, è possibile riassegnare una variabile locale Ref local o ref ReadOnly con l' operatore di assegnazione Ref.Also beginning with C# 7.3, you can reassign a ref local or ref readonly local variable with the ref assignment operator.

Variabili ref readonlyRef readonly locals

Un oggetto locale Ref ReadOnly viene usato per fare riferimento ai valori restituiti da un metodo o da una proprietà che ha ref readonly nella firma e USA return ref .A ref readonly local is used to refer to values returned by a method or property that has ref readonly in its signature and uses return ref. Una ref readonly variabile combina le proprietà di una ref variabile locale con una readonly variabile, ovvero un alias per l'archiviazione a cui è assegnata e non può essere modificata.A ref readonly variable combines the properties of a ref local variable with a readonly variable: it's 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

Specifiche del linguaggio C#C# language specification

Per ulteriori 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.

Vedi ancheSee also