ref (Справочник по C#)

Ключевое слово ref используется для передачи аргумента по ссылке, а не по значению. Эффект передачи по ссылке в том, что все изменения вызываемого метода отражаются на значении переменной аргумента, используемой в вызове метода. Например если вызывающий объект передает выражение локальной переменной или выражение доступа к элементу массива и вызванный метод заменяет объект, на который ссылается параметр ref, то локальная переменная или элемент массива взывающего объекта теперь ссылаться на новый объект.

Примечание

Не следует путать понятие передачи по ссылке с понятием ссылочных типов.Эти два понятия не совпадают.Параметр метода может быть изменен с помощью ref независимо от того, принадлежит ли он к типу значения или ссылочному типу.При передаче по ссылке упаковка-преобразование типа значения не производится.

Для использования параметра ref и при определении метода, и при вызове метода следует явно использовать ключевое слово ref, как показано в следующем примере.

    class RefExample
    {
        static void Method(ref int i)
        {
            // Rest the mouse pointer over i to verify that it is an int. 
            // The following statement would cause a compiler error if i 
            // were boxed as an object.
            i = i + 44;
        }

        static void Main()
        {
            int val = 1;
            Method(ref val);
            Console.WriteLine(val);

            // Output: 45
        }
    }

Аргумент, передаваемый в параметр ref, перед передачей должен быть инициализирован. В этом заключается отличие от параметров out, аргументы которых не требуют явной инициализации перед передачей. Дополнительные сведения см. в разделе out.

Члены класса не могут иметь сигнатуры, отличие которых заключается только в ref и out. Если единственное различие между двумя членами типа состоит в том, что один из них имеет параметр ref, а второй имеет параметр out, возникает ошибка компилятора. Например, следующий код не будет компилироваться.

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

Однако перегрузка может быть выполнена, если один метод принимает параметр ref или out, а другой принимает параметр по значению, как показано в следующем примере.

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

В других ситуациях, требующих соответствия сигнатур, таких как скрытие или переопределение, ref и out являются частью сигнатуры и не соответствуют друг другу.

Свойства не являются переменными. Они являются методами и не могут быть переданы в параметр ref.

Дополнительные сведения о передаче массивов см. в разделе Передача массивов при помощи параметров ref и out (Руководство по программированию на C#).

Ключевые слова ref и out нельзя использовать для следующих типов методов.

  • Асинхронные методы, которые определяются с помощью модификатора async.

  • Методы итератора, которые включают оператор yield return или yield break.

Пример

В предыдущих примерах показано, что происходит при передаче типов значений по ссылке. Можно также использовать ключевое слово ref для передачи ссылочных типов. Передача ссылочного типа по ссылке позволяет вызываемому методу изменять объект, на который указывает ссылочный параметр. Место хранения объекта передается методу в качестве значения ссылочного параметра. Если изменить место хранения параметра (с указанием на новый объект), необходимо изменить место хранения, на который ссылается вызывающий объект. В следующем примере экземпляр ссылочного типа передается как параметр ref. Дополнительные сведения о передаче ссылочных типов по значению и по ссылке см. в разделе Передача параметров ссылочного типа (Руководство по программированию в C#).

class RefExample2
{
    static void ChangeByReference(ref Product itemRef)
    {
        // The following line changes the address that is stored in   
        // parameter itemRef. Because itemRef is a ref parameter, the 
        // address that is stored in variable item in Main also is changed.
        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;
    }

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

        // Send item to ChangeByReference as a ref argument.
        ChangeByReference(ref item);
        System.Console.WriteLine("Back in Main.  Name: {0}, ID: {1}\n",
            item.ItemName, item.ItemID);
    }
}

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

Спецификация языка C#

Дополнительные сведения см. в Спецификация языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также

Ссылки

Передача параметров (Руководство по программированию в C#)

Параметры методов (Справочник по C#)

Ключевые слова C#

Основные понятия

Руководство по программированию на C#

Другие ресурсы

Справочник по C#