ref (C#-Referenz)

Das ref-Schlüsselwort gibt einen Wert an, der als Verweis übergeben wird. Es wird in drei unterschiedlichen Kontexten verwendet:

  • In einer Methodensignatur und in einem Methodenaufruf, um ein Argument an eine Methode als Verweis zu übergeben. Weitere Informationen finden Sie unter Passing an argument by reference (Übergeben eines Arguments als Verweis).

  • In einer Methodensignatur, um einen Wert an den Aufrufer als Verweis zurückzugeben. Weitere Informationen finden Sie unter Verweisrückgabewerte.

  • In einem Memberkörper, um anzugeben, dass ein Verweisrückgabewert lokal als Verweis, den der Aufrufer ändern möchte, gespeichert wird. Weitere Informationen finden Sie unter Lokale ref-Variablen.

Übergeben eines Arguments als Verweis

In der Parameterliste einer Methode gibt das ref-Schlüsselwort an, dass ein Argument als Verweis und nicht als Wert übergeben wird. Durch das Übergeben als Verweis wird jede Änderung am Argument in der aufgerufenen Methode in der aufrufenden Methode wiedergegeben. Wenn der Aufrufer z.B. einen lokalen Variablenausdruck oder einen Arrayelement-Zugriffsausdruck übergibt und die aufgerufene Methode das Objekt ersetzt, auf das der ref-Parameter verweist, dann verweist die lokale Variable des Aufrufers oder das Arrayelement jetzt auf das neue Objekt, wenn die Methode zurückgibt.

Hinweis

Verwechseln Sie nicht das Konzept der Übergabe durch einen Verweis mit dem Konzept der Verweistypen. Die beiden Konzepte sind nicht identisch. Ein Methodenparameter kann durch ref geändert werden, unabhängig davon, ob es sich um einen Werttyp oder ein Verweistyp handelt. Es gibt keine Boxing-Konvertierung eines Werttyps, wenn er durch einen Verweis übergeben wird.

Um einen ref-Parameter zu verwenden, müssen sowohl die Methodendefinition als auch die aufrufende Methode explizit das Schlüsselwort ref verwenden, wie im folgenden Beispiel gezeigt.

class RefExample
{
    static void Method(ref int i)
    {
        i = i + 44;
    }

    static void Main()
    {
        int val = 1;
        Method(ref val);
        Console.WriteLine(val);
        // Output: 45
    }
}

Ein Argument, das an einen ref-Parameter übergeben wird, muss vor der Übergabe initialisiert werden. Dies unterscheidet sich von den out-Parametern, deren Argumente nicht explizit initialisiert werden müssen, bevor sie übergeben werden.

Member einer Klasse können keine Signaturen haben, die sich nur durch ref und out voneinander unterscheiden. Es tritt ein Compilerfehler auf, wenn der einzige Unterschied zwischen beiden Member eines Typs der ist, dass einer von ihnen über einen ref-Parameter und der andere über einen out-Parameter verfügt. Der folgende Code wird z. B. nicht kompiliert.

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) { }
}

Allerdings können Methoden überladen werden, wenn eine Methode einen ref- oder out-Parameter hat und die andere über einen Werteparameter verfügt, wie im folgenden Beispiel gezeigt.

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

In anderen Situationen, die eine Signaturabstimmung benötigen, z. B. beim Ausblenden oder Überschreiben, sind ref und out Bestandteil der Signatur und passen nicht zueinander.

Eigenschaften sind keine Variablen. Sie sind Methoden und können nicht an ref-Parameter übergeben werden.

Weitere Informationen zum Übergeben von Arrays finden Sie unter Übergeben von Arrays mithilfe von „ref“ und „out“.

Sie können keines der beiden Schlüsselwörter ref und out für die folgenden Methodentypen verwenden:

  • Asynchrone Methoden, die Sie mit dem async-Modifizierer definieren.

  • Iterator-Methoden, die eine yield return- oder yield break-Anweisung enthalten.

Übergeben eines Arguments als Verweis: Beispiel

In den vorherigen Beispielen wurden Werttypen als Verweis übergeben. Sie können das ref-Schlüsselwort auch verwenden, um Verweistypen als Verweis zu übergeben. Die Übergabe eines Verweistyps als Verweis ermöglicht es der aufgerufenen Methode, das Objekt, auf die der Verweisparameter im Aufrufer verweist, zu ersetzen. Der Speicherort des Objekts wird als Wert des Verweisparameters an die Methode übergeben. Wenn Sie den Wert am Speicherort des Parameters ändern (um auf ein neues Objekt zu verweisen), ändern Sie auch den Speicherort, auf den der Aufrufer verweist. Im folgenden Beispiel wird eine Instanz eines Verweistyps als ein ref-Parameter übergeben.

class RefExample2
{
    static void Main()
    {
        // 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);
    }

    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;
    }
}

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

    public string ItemName { get; set; }
    public int ItemID { get; set; }
}
// Output: 
//        Original values in Main.  Name: Fasteners, ID: 54321
//    
//        Back in Main.  Name: Stapler, ID: 12345

Weitere Informationen zum Übergeben von Verweistypen durch einen Wert und durch einen Verweis finden Sie unter Übergeben von Verweistypparametern.

Verweisrückgabewerte

Verweisrückgabewerte (auch ref-Rückgaben genannt) sind Werte, die von einer Methode an den Aufrufer als Verweis zurückgegeben werden. Das bedeutet, dass der Aufrufer den von einer Methode zurückgegebenen Wert ändern kann. Diese Änderung wird im Zustand des Objekts, das die Methode enthält, wiedergegeben.

Ein Verweisrückgabewert wird definiert durch Verwenden des ref-Schlüsselworts:

  • In der Methodensignatur. Die folgende Methodensignatur gibt z.B. an, dass die Methode GetCurrentPrice den Wert <xref:System.Decimal> als Verweis zurückgibt.

    public ref decimal GetCurrentValue()
    
  • Vor jeder return-Anweisung in der Methode. Zum Beispiel:

    ref return Decimal.Zero;
    

Zum Ändern des Zustands des Objekts durch den Aufrufer muss der Verweisrückgabewert in einer Variable gespeichert werden, die explizit als lokale ref-Variable definiert wird.

Ein Beispiel finden Sie unter Beispiel für ref-Rückgaben und lokale ref-Variablen.

Lokale ref-Variablen

Eine lokale ref-Variable wird verwendet, um auf Werte zu verweisen, die mit ref return zurückgegeben werden. Eine lokale ref-Variable muss initialisiert und einem ref-Rückgabewert zugewiesen werden. Jede Änderung am Wert der lokalen ref-Variable wird im Zustand des Objekts wiedergegeben, dessen Methode den Wert als Verweis zurückgegeben hat.

Eine lokale ref-Variable wird mithilfe des ref-Schlüsselworts vor der Variablendeklaration definiert sowie unmittelbar vor dem Aufruf der Methode, die den Wert als Verweis zurückgibt.

Die folgende Anweisung definiert z.B. eine lokale ref-Variable, die von der Methode GetEstimatedValue zurückgegeben wird:

ref decimal estValue = ref Building.GetEstimatedValue();

Beachten Sie, dass das ref-Schlüsselwort an beiden Stellen verwendet werden muss. Andernfalls generiert der Compiler den Fehler CS8172 „Eine by-reference-Variable kann nicht mit einem Wert initialisiert werden“.

Beispiel für ref-Rückgaben und lokale ref-Variablen

Im folgenden Beispiel wird eine Book-Klasse mit zwei <xref:System.String>-Feldern definiert: Title und Author. Außerdem wird eine BookCollection-Klasse definiert, die ein privates Array von Book-Objekten enthält. Einzelne Buchobjekte werden durch Aufrufen der GetBookByTitle-Methode als Verweis zurückgegeben.

using System;

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();   
   } 
}

Speichert der Aufrufer den von der GetBookByTitle-Methode zurückgegeben Wert als lokale ref-Variable, werden Änderungen, die der Aufrufer am Rückgabewert vornimmt, im BookCollection-Objekt wiedergegeben. Dies wird im folgenden Beispiel gezeigt:

using System;

class Example
{
   static void Main()
   {
      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

C#-Programmiersprachenspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch

C#-Referenz
C#-Programmierhandbuch
Übergeben von Parametern
Methodenparameter
C#-Schlüsselwörter