ref (Referenční dokumentace jazyka C#)ref (C# Reference)

ref Klíčové slovo označuje hodnotu, která je předána odkazem.The ref keyword indicates a value that is passed by reference. Používá se ve čtyřech různých kontextech:It is used in four different contexts:

  • V signatuře metody a ve volání metody předejte argument metodě odkazem.In a method signature and in a method call, to pass an argument to a method by reference. Další informace naleznete v tématu předání argumentu odkazem.For more information, see Passing an argument by reference.
  • V signatuře metody pro vrácení hodnoty volajícímu odkazem.In a method signature, to return a value to the caller by reference. Další informace najdete v tématu referenční návratové hodnoty.For more information, see Reference return values.
  • V těle člena, aby označoval, že návratová hodnota odkazu je uložená místně jako odkaz, který volající chce změnit, nebo obecně místní proměnná přistupuje k jiné hodnotě odkazem.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. Další informace naleznete v tématu místní hodnoty REF.For more information, see Ref locals.
  • V deklaraci pro ref struct deklaraci nebo readonly ref struct. structIn a struct declaration to declare a ref struct or a readonly ref struct. Další informace naleznete v tématu typy referenční struktury.For more information, see ref struct types.

Předání argumentu odkazemPassing an argument by reference

Při použití v seznamu ref parametrů metody označuje klíčové slovo, že argument je předán odkazem, nikoli hodnotou.When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. ref Klíčové slovo nastaví formální parametr jako alias pro argument, který musí být proměnná.The ref keyword makes the formal parameter an alias for the argument, which must be a variable. Jinými slovy, každá operace s parametrem je provedena na argumentu.In other words, any operation on the parameter is made on the argument. Například pokud volající předává výraz místní proměnné nebo výraz přístupu k elementu pole a volaná metoda nahradí objekt, na který odkazuje parametr ref, pak místní proměnná volajícího nebo prvek pole nyní odkazuje na nový objekt, když Metoda vrací.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.

Poznámka

Nepleťte si koncept předávání odkazem s konceptem typů odkazů.Do not confuse the concept of passing by reference with the concept of reference types. Tyto dvě koncepce nejsou stejné.The two concepts are not the same. Parametr metody lze změnit ref bez ohledu na to, zda se jedná o typ hodnoty nebo typ odkazu.A method parameter can be modified by ref regardless of whether it is a value type or a reference type. Pokud je předána odkazem, není k dispozici žádný zabalení typu hodnoty.There is no boxing of a value type when it is passed by reference.

Chcete-li ref použít parametr, definice metody a volající metoda musí explicitně ref používat klíčové slovo, jak je znázorněno v následujícím příkladu.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

Argument, který je předán ref parametru nebo in , musí být inicializován před předáním.An argument that is passed to a ref or in parameter must be initialized before it is passed. To se liší od parametrů out , jejichž argumenty není nutné před předáním explicitně inicializovat.This differs from out parameters, whose arguments do not have to be explicitly initialized before they are passed.

Členové třídy nemohou mít signatury, které se liší pouze refpomocí in, nebo out.Members of a class can't have signatures that differ only by ref, in, or out. K chybě kompilátoru dojde, pokud jediným rozdílem mezi dvěma členy typu je, že jeden z nich má ref parametr a druhý outmá parametr, nebo 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. Následující kód například není zkompilován.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) { }
}

Nicméně metody mohou být přetíženy v případě ref, že jedna metoda má parametr, innebo out a druhá má parametr hodnoty, jak je znázorněno v následujícím příkladu.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) { }
}

V jiných situacích, které vyžadují porovnávání signatur, jako je například skrytí nebo inpřepsání ref,, out a jsou součástí podpisu a vzájemně se neshodují.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.

Vlastnosti nejsou proměnné.Properties are not variables. Jsou to metody a nelze je předat ref parametrům.They are methods, and cannot be passed to ref parameters.

Klíčová slova ref, ina out nelze použít pro následující typy metod:You can't use the ref, in, and out keywords for the following kinds of methods:

  • Asynchronní metody, které definujete pomocí modifikátoru Async .Async methods, which you define by using the async modifier.
  • Metody iterátoru, které zahrnují návratový návrat nebo yield break příkaz yield.Iterator methods, which include a yield return or yield break statement.

Předání argumentu odkazem: PříkladPassing an argument by reference: An example

Předchozí příklady přecházejí typu hodnoty odkazem.The previous examples pass value types by reference. Můžete také použít ref klíčové slovo k předání typu odkazu odkazem.You can also use the ref keyword to pass reference types by reference. Předání typu odkazu odkazem umožňuje volané metodě nahradit objekt, na který odkazuje parametr reference v volajícím.Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller. Umístění úložiště objektu je předáno metodě jako hodnota referenčního parametru.The storage location of the object is passed to the method as the value of the reference parameter. Změníte-li hodnotu v umístění úložiště parametru (aby odkazovala na nový objekt), můžete také změnit umístění úložiště, do kterého se volající odkazuje.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. Následující příklad předává instanci typu odkazu jako ref parametr.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        

Další informace o tom, jak předat typy odkazů podle hodnoty a odkazu, naleznete v tématu předávání parametrů typu odkazu.For more information about how to pass reference types by value and by reference, see Passing Reference-Type Parameters.

Referenční návratové hodnotyReference return values

Návratové hodnoty odkazu (nebo ref vrátí) jsou hodnoty, které metoda vrátí odkazem na volajícího.Reference return values (or ref returns) are values that a method returns by reference to the caller. To znamená, že volající může změnit hodnotu vrácenou metodou a tato změna se projeví ve stavu objektu, který obsahuje metodu.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.

Návratová hodnota odkazu je definována pomocí ref klíčového slova:A reference return value is defined by using the ref keyword:

  • V signatuře metody.In the method signature. Například následující signatura metody označuje, že GetCurrentPrice metoda Decimal vrací hodnotu odkazem.For example, the following method signature indicates that the GetCurrentPrice method returns a Decimal value by reference.
public ref decimal GetCurrentPrice()
  • Mezi tokenem a proměnnou vrácenou return v příkazu v metodě. returnBetween the return token and the variable returned in a return statement in the method. Příklad:For example:
return ref DecimalArray[0];

Aby mohl volající změnit stav objektu, návratová hodnota odkazu musí být uložena do proměnné, která je explicitně definována jako místní referenčníčíslo.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.

Volaná metoda může také deklarovat návratovou hodnotu ref readonly tak, aby vracela hodnotu odkazem a vynutila, že volající kód nemůže změnit vrácenou hodnotu.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. Volající metoda se může vyhnout zkopírování vracené hodnoty tím, že uloží hodnotu v proměnné s parametrem ReadOnly .The calling method can avoid copying the returned valued by storing the value in a local ref readonly variable.

Příklad naleznete v části ref Returns a lokální hodnoty REF.For an example, see A ref returns and ref locals example.

Lokální hodnoty REFRef locals

Lokální proměnná ref slouží k odkazování na hodnoty vrácené pomocí return ref.A ref local variable is used to refer to values returned using return ref. Lokální proměnnou ref nelze inicializovat pro návratovou hodnotu, která není ref.A ref local variable cannot be initialized to a non-ref return value. Jinými slovy, pravé straně inicializace musí být odkaz.In other words, the right hand side of the initialization must be a reference. Jakékoli úpravy hodnoty lokálního odkazu se projeví ve stavu objektu, jehož metoda vrátila hodnotu odkazem.Any modifications to the value of the ref local are reflected in the state of the object whose method returned the value by reference.

Místní odkaz definujete pomocí ref klíčového slova před deklaraci proměnné, stejně jako bezprostředně před voláním metody, která vrací hodnotu odkazem.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.

Například následující příkaz definuje místní hodnotu REF, která je vrácena metodou s názvem 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();

K hodnotě můžete přistupovat stejným způsobem pomocí odkazu.You can access a value by reference in the same way. V některých případech přístup k hodnotě pomocí odkazu zvyšuje výkon tím, že se vyhne potenciálně nákladné operaci kopírování.In some cases, accessing a value by reference increases performance by avoiding a potentially expensive copy operation. Například následující příkaz ukazuje, jak může jeden definovat místní hodnotu REF, která se používá k odkazování na hodnotu.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;

Všimněte si, že v obou ref příkladech je klíčové slovo nutné použít na obou místech, nebo kompilátor generuje chybu CS8172, "" nemůže inicializovat proměnnou podle odkazu s hodnotou. "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."

Počínaje C# 7,3 se proměnná foreach iterace příkazu může jednat o místní proměnnou ref nebo ref jen pro čtení.Beginning with C# 7.3, the iteration variable of the foreach statement can be ref local or ref readonly local variable. Další informace naleznete v článku o příkazu foreach .For more information, see the foreach statement article.

Místní referenční hodnoty jen pro čteníRef readonly locals

Místní odkaz jen pro čtení se používá k odkazování na hodnoty vracené metodou nebo vlastností, ref readonly která má jeho signaturu return refa používá.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. Proměnná kombinuje vlastnosti ref místní proměnné s readonly proměnnou: Jedná se o alias úložiště, ke kterému je přiřazený, a nedá se změnit. ref readonlyA 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.

Příklad odkazů vrátí a místní hodnoty REFA ref returns and ref locals example

Následující příklad definuje Book třídu, která má dvě String pole Title a Author.The following example defines a Book class that has two String fields, Title and Author. Definuje BookCollection také třídu, která obsahuje soukromé Book pole objektů.It also defines a BookCollection class that includes a private array of Book objects. Jednotlivé objekty knihy jsou vráceny odkazem voláním její GetBookByTitle metody.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();
    }
}

Když volající ukládá hodnotu vrácenou GetBookByTitle metodou jako místní referenční číslo, změny, které volající provede na vrácenou hodnotu, se projeví BookCollection v objektu, jak ukazuje následující příklad.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

Typy referenční strukturyRef struct types

Přidání modifikátoru struct k deklaraci definuje, že instance daného typu musí být přiděleny zásobníku. refAdding the ref modifier to a struct declaration defines that instances of that type must be stack allocated. Jinými slovy, instance těchto typů nelze nikdy vytvořit v haldě jako člen jiné třídy.In other words, instances of these types can never be created on the heap as a member of another class. Primární motivace pro tuto funkci byla Span<T> a související struktury.The primary motivation for this feature was Span<T> and related structures.

Cílem zachování ref struct typu jako proměnné přidělené zásobníku je několik pravidel, která kompilátor vynutil pro všechny ref struct typy.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.

  • Nemůžete pole ref structa.You can't box a ref struct. Nelze přiřadit ref struct typ k proměnné typu object, dynamicnebo žádnému typu rozhraní.You cannot assign a ref struct type to a variable of type object, dynamic, or any interface type.
  • ref structtypy nemohou implementovat rozhraní.ref struct types cannot implement interfaces.
  • Nelze deklarovat ref struct jako člena pole třídy nebo normální struktury.You can't declare a ref struct as a field member of a class or a normal struct. To zahrnuje deklaraci automaticky implementované vlastnosti, která vytvoří pole pro zálohování generované kompilátorem.This includes declaring an auto-implemented property, which creates a compiler generated backing field.
  • Nelze deklarovat lokální proměnné, které jsou ref struct typy v asynchronních metodách.You cannot declare local variables that are ref struct types in async methods. Můžete je deklarovat v synchronních metodách, Taskkteré Task<TResult> vracejí Tasknebo jako typy.You can declare them in synchronous methods that return Task, Task<TResult> or Task-like types.
  • V iterátorech ref struct nelze deklarovat lokální proměnné.You cannot declare ref struct local variables in iterators.
  • Nemůžete ref struct zachytit proměnné ve výrazech lambda nebo místních funkcích.You cannot capture ref struct variables in lambda expressions or local functions.

Tato omezení zajišťují, že nechtěně nepoužíváte ref struct způsobem, který by ho mohl zvýšit na spravovanou haldu.These restrictions ensure you don't accidentally use a ref struct in a manner that could promote it to the managed heap.

Můžete kombinovat modifikátory a deklarovat strukturu jako readonly ref.You can combine modifiers to declare a struct as readonly ref. Kombinuje výhody a ref struct omezení a readonly struct deklarace. readonly ref structA readonly ref struct combines the benefits and restrictions of ref struct and readonly struct declarations.

specifikace jazyka C#C# language specification

Další informace najdete v tématu Specifikace jazyka C#.For more information, see the C# Language Specification. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.The language specification is the definitive source for C# syntax and usage.

Viz také:See also