ref (Referência de C#)ref (C# Reference)

A palavra-chave ref indica um valor que é passado por referência.The ref keyword indicates a value that is passed by reference. Ela é usada em quatro contextos diferentes:It is used in four different contexts:

  • Em uma assinatura de método e em uma chamada de método, para passar um argumento a um método por referência.In a method signature and in a method call, to pass an argument to a method by reference. Para obter mais informações, veja Passar um argumento por referência.For more information, see Passing an argument by reference.
  • Em uma assinatura de método para retornar um valor para o chamador por referência.In a method signature, to return a value to the caller by reference. Para obter mais informações, consulte Reference return values (Valores retornados de referência).For more information, see Reference return values.
  • Em um corpo de membro, para indicar que um valor retornado por referência é armazenado localmente como uma referência que o chamador pretende modificar ou, em geral, uma variável local acessa outro valor por referência.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. Para obter mais informações, veja Locais de referência.For more information, see Ref locals.
  • Em uma declaração struct para declarar um ref struct ou um readonly ref struct.In a struct declaration to declare a ref struct or a readonly ref struct. Para obter mais informações, consulte a seção ref struct do artigo tipos de estrutura .For more information, see the ref struct section of the Structure types article.

Passando um argumento por referênciaPassing an argument by reference

Quando usado na lista de parâmetros do método, a palavra-chave ref indica que um argumento é passado por referência, não por valor.When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. A palavra-chave ref torna o parâmetro formal um alias para o argumento, que deve ser uma variável.The ref keyword makes the formal parameter an alias for the argument, which must be a variable. Em outras palavras, qualquer operação no parâmetro é feita no argumento.In other words, any operation on the parameter is made on the argument. Por exemplo, se o chamador passar uma expressão de variável local ou uma expressão de acesso de elemento de matriz, e o método chamado substituir o objeto ao qual o parâmetro ref se refere, a variável local do chamador ou o elemento de matriz agora se referirá ao novo objeto quando o método retornar.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.

Observação

Não confunda o conceito de passar por referência com o conceito de tipos de referência.Do not confuse the concept of passing by reference with the concept of reference types. Os dois conceitos não são iguais.The two concepts are not the same. Um parâmetro de método pode ser modificado por ref, independentemente de ele ser um tipo de valor ou um tipo de referência.A method parameter can be modified by ref regardless of whether it is a value type or a reference type. Não há nenhuma conversão boxing de um tipo de valor quando ele é passado por referência.There is no boxing of a value type when it is passed by reference.

Para usar um parâmetro ref, a definição do método e o método de chamada devem usar explicitamente a palavra-chave ref, como mostrado no exemplo a seguir.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

Um argumento passado para um parâmetro ref ou in precisa ser inicializado antes de ser passado.An argument that is passed to a ref or in parameter must be initialized before it is passed. Isso é diferente dos parâmetros out, cujos argumentos não precisam ser inicializados explicitamente antes de serem passados.This differs from out parameters, whose arguments do not have to be explicitly initialized before they are passed.

Os membros de uma classe não podem ter assinaturas que se diferem somente por ref, in ou out.Members of a class can't have signatures that differ only by ref, in, or out. Ocorrerá um erro de compilador se a única diferença entre os dois membros de um tipo for que um deles tem um parâmetro ref e o outro tem um parâmetro out ou 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. O código a seguir, por exemplo, não é compilado.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) { }
}

No entanto, os métodos podem ser sobrecarregados quando um método tem um parâmetro ref, in ou out e o outro tem um parâmetro de valor, conforme é mostrado no exemplo a seguir.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) { }
}

Em outras situações que exigem correspondência de assinatura, como ocultar ou substituir, in, ref e out fazem parte da assinatura e não são correspondentes.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.

Propriedades não são variáveis.Properties are not variables. Elas são métodos e não podem ser passadas para parâmetros ref.They are methods, and cannot be passed to ref parameters.

Não é possível usar as palavras-chave ref, in e out para os seguintes tipos de métodos:You can't use the ref, in, and out keywords for the following kinds of methods:

  • Métodos assíncronos, que você define usando o modificador async.Async methods, which you define by using the async modifier.
  • Métodos de iterador, que incluem uma instrução yield return ou yield break.Iterator methods, which include a yield return or yield break statement.

Além disso, os métodos de extensão têm as seguintes restrições:In addition, extension methods have the following restrictions:

  • A out palavra-chave não pode ser usada no primeiro argumento de um método de extensão.The out keyword cannot be used on the first argument of an extension method.
  • A ref palavra-chave não pode ser usada no primeiro argumento de um método de extensão quando o argumento não é um struct ou um tipo genérico não restrito a ser um 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.
  • A in palavra-chave não pode ser usada, a menos que o primeiro argumento seja um struct.The in keyword cannot be used unless the first argument is a struct. A in palavra-chave não pode ser usada em nenhum tipo genérico, mesmo quando restrita a um struct.The in keyword cannot be used on any generic type, even when constrained to be a struct.

Passando um argumento por referência: um exemploPassing an argument by reference: An example

Os exemplos anteriores passam tipos de valor por referência.The previous examples pass value types by reference. Você também pode usar a palavra-chave ref para passar tipos de referência por referência.You can also use the ref keyword to pass reference types by reference. Passar um tipo de referência por referência permite que o método chamado substitua o objeto ao qual se refere o parâmetro de referência no chamador.Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller. O local de armazenamento do objeto é passado para o método como o valor do parâmetro de referência.The storage location of the object is passed to the method as the value of the reference parameter. Se você alterar o valor no local de armazenamento do parâmetro (para apontar para um novo objeto), irá alterar também o local de armazenamento ao qual se refere o chamador.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. O exemplo a seguir passa uma instância de um tipo de referência como um parâmetro 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

Para obter mais informações sobre como passar tipos de referência por valor e por referência, consulte Passando parâmetros de tipo de referência.For more information about how to pass reference types by value and by reference, see Passing Reference-Type Parameters.

Valores retornados por referênciaReference return values

Valores retornados por referência (ou ref returns) são valores que um método retorna por referência para o chamador.Reference return values (or ref returns) are values that a method returns by reference to the caller. Ou seja, o chamador pode modificar o valor retornado por um método e essa alteração é refletida no estado do objeto no método de chamada.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.

Um valor retornado por referência é definido usando a palavra-chave ref:A reference return value is defined by using the ref keyword:

  • Na assinatura do método.In the method signature. Por exemplo, a assinatura de método a seguir indica que o método GetCurrentPrice retorna um valor Decimal por referência.For example, the following method signature indicates that the GetCurrentPrice method returns a Decimal value by reference.
public ref decimal GetCurrentPrice()
  • Entre o token return e a variável retornada em uma instrução return no método.Between the return token and the variable returned in a return statement in the method. Por exemplo:For example:
return ref DecimalArray[0];

Para que o chamador modifique o estado do objeto, o valor retornado de referência deve ser armazenado em uma variável que é definida explicitamente como um ref local.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.

Aqui está um exemplo de retorno de referência mais completo, mostrando a assinatura do método e o corpo do método.Here is 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");
}

O método chamado também poderá declarar o valor retornado como ref readonly para retornar o valor por referência e, em seguida, impor que o código de chamada não possa modificar o valor retornado.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. O método de chamada pode evitar a cópia retornada com um valor ao armazenar o valor em um local ref readonly variável.The calling method can avoid copying the returned valued by storing the value in a local ref readonly variable.

Para obter um exemplo, consulte um exemplo de referências de ref e ref local.For an example, see A ref returns and ref locals example.

Ref localsRef locals

Uma variável de ref local é usada para fazer referência a valores retornados usando return ref.A ref local variable is used to refer to values returned using return ref. Uma variável local ref não pode ser inicializada para um valor retornado que não seja ref.A ref local variable cannot be initialized to a non-ref return value. Em outras palavras, o lado direito da inicialização deve ser uma referência.In other words, the right-hand side of the initialization must be a reference. Todas as modificações ao valor do ref local são refletidas no estado do objeto cujo método retornou o valor por referência.Any modifications to the value of the ref local are reflected in the state of the object whose method returned the value by reference.

Você define um ref local usando a palavra-chave ref antes da declaração de variável, bem como imediatamente antes da chamada para o método que retorna o valor por referência.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.

Por exemplo, a instrução a seguir define um valor de ref local que é retornado por um método chamado 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();

Você pode acessar um valor por referência da mesma maneira.You can access a value by reference in the same way. Em alguns casos, acessar um valor por referência aumenta o desempenho, evitando uma operação de cópia potencialmente dispendiosa.In some cases, accessing a value by reference increases performance by avoiding a potentially expensive copy operation. Por exemplo, a instrução a seguir mostra como é possível definir um valor de local de ref que é usado para fazer referência a um valor.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;

Em ambos os exemplos ref , a palavra-chave deve ser usada em ambos os locais ou o compilador gera o erro CS8172, "não é possível inicializar uma variável por referência com um valor".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 partir do C# 7.3, a variável de iteração da instrução foreach pode ser ref local ou a variável local ref readonly.Beginning with C# 7.3, the iteration variable of the foreach statement can be ref local or ref readonly local variable. Para saber mais, confira o artigo Instrução foreach.For more information, see the foreach statement article.

Além de começar com o C# 7,3, você pode reatribuir uma variável local ref local ou ref ReadOnly com o operador ref Assignment.Also beginning with C# 7.3, you can reassign a ref local or ref readonly local variable with the ref assignment operator.

Locais somente leitura de referênciaRef readonly locals

Um local ref readonly é usado para fazer referência a valores retornados pelo método ou propriedade que tem ref readonly na sua assinatura 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. Uma variável ref readonly combina as propriedades de uma variável ref local com uma variável readonly: é um alias para o armazenamento ao qual está atribuído e não pode ser modificado.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.

Um exemplo de ref returns e ref localsA ref returns and ref locals example

O exemplo a seguir define uma classe Book que tem dois campos String, Title e Author.The following example defines a Book class that has two String fields, Title and Author. Ele também define uma classe BookCollection que inclui uma matriz privada de objetos Book.It also defines a BookCollection class that includes a private array of Book objects. Objetos de catálogo individuais são retornados por referência chamando o respectivo método 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 o chamador armazena o valor retornado pelo método GetBookByTitle como um ref local, as alterações que o chamador faz ao valor retornado são refletidas no objeto BookCollection, conforme mostra o exemplo a seguir.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

Especificação da linguagem C#C# language specification

Para obter mais informações, consulte a especificação da linguagem C#.For more information, see the C# Language Specification. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.The language specification is the definitive source for C# syntax and usage.

Confira tambémSee also