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 ref readonly struct.In a struct declaration to declare a ref struct or a ref readonly struct. Para obter mais informações, veja tipos ref struct.For more information, see ref struct types.

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 passa uma expressão variável local ou uma expressão de acesso do elemento de matriz e o método chamado substituir o objeto ao qual o parâmetro ref se refere, então a variável local do chamador ou o elemento da matriz fará agora referência 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.

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 será refletida no estado do objeto que contém o método.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.

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.

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 ref returns e ref locals.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;

Observe que, nos dois exemplos, a palavra-chave ref 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".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 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.

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

Tipos struct de referênciaRef struct types

Adicionar o modificador ref a uma declaração struct define que instâncias desse tipo devem ser alocadas por pilha.Adding the ref modifier to a struct declaration defines that instances of that type must be stack allocated. Em outras palavras, instâncias desses tipos nunca podem ser criados no heap como um membro de outra classe.In other words, instances of these types can never be created on the heap as a member of another class. A principal motivação para esse recurso foi Span<T> e as estruturas relacionadas.The primary motivation for this feature was Span<T> and related structures.

A meta de manter um tipo ref struct como uma variável alocada na pilha apresenta várias regras que o compilador aplica para todos os tipos 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.

  • Você não pode encaixotar um ref struct.You can't box a ref struct. Você não pode atribuir um tipo ref struct a uma variável do tipo object, dynamic ou de qualquer tipo de interface.You cannot assign a ref struct type to a variable of type object, dynamic, or any interface type.
  • Tipos ref struct não podem implementar interfaces.ref struct types cannot implement interfaces.
  • Você não pode declarar um ref struct como um membro de uma classe ou de um struct normal.You can't declare a ref struct as a member of a class or a normal struct.
  • Você não pode declarar variáveis locais que são do tipo ref struct em métodos assíncronos.You cannot declare local variables that are ref struct types in async methods. Você pode declará-las em métodos síncronos que retornam tipos semelhantes a Task, Task<TResult> ou Task.You can declare them in synchronous methods that return Task, Task<TResult> or Task-like types.
  • Você não pode declarar as variáveis locais ref struct em iteradores.You cannot declare ref struct local variables in iterators.
  • Você não pode capturar as variáveis ref struct em expressões lambda ou em funções locais.You cannot capture ref struct variables in lambda expressions or local functions.

Essas restrições garantem que você não use acidentalmente um ref struct de maneira que possa promovê-lo para o heap gerenciado.These restrictions ensure you don't accidentally use a ref struct in a manner that could promote it to the managed heap.

Você pode combinar modificadores para declarar um struct como readonly ref.You can combine modifiers to declare a struct as readonly ref. Um readonly ref struct combina os benefícios e as restrições de declarações ref struct e readonly struct.A readonly ref struct combines the benefits and restrictions of ref struct and readonly struct declarations.

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.

Consulte tambémSee also