Разница между параметрами ref и out в .NET [дубликаты]

409

В чем разница между параметрами ref и out в .NET? Каковы ситуации, когда можно быть более полезными, чем другие? Что было бы фрагментом кода, где можно было бы использовать, а другое не могло?

Теги:

18 ответов

501
Лучший ответ

Они почти одинаковы - единственное отличие состоит в том, что переменную, которую вы передаете как параметр out, не нужно инициализировать, но передавая ее как параметр ref, она должна быть установлена ​​на что-то.

int x;
Foo(out x); // OK

int y;
Foo(ref y); // Error: y should be initialized before calling the method

ref параметры для данных, которые могут быть изменены, out параметры для данных, которые являются дополнительным выходом для функции (например, int.TryParse), которые уже используют возвращаемое значение для чего-то.

  • 94
    Кроме того, параметры out должны быть установлены во время выполнения вызываемого абонента перед возвратом к вызывающему абоненту, который противоположен ref, который должен быть установлен вызывающим абонентом перед вызовом вызываемого абонента.
  • 3
    @ Майк Твое исправление НЕПРАВИЛЬНО. Это было правильно "и метод, использующий параметр out, должен что-то установить". Метод, получающий параметр out должен его инициализировать. Метод, получающий параметр ref может делать с ним то, что он хочет. Это может конечно игнорировать это. Я возвращаюсь назад.
Показать ещё 5 комментариев
124

Почему у С# есть как 'ref', так и 'out'?

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

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

Итак, out означает, а ref - для входа и выхода.

Они тесно соответствуют параметрам [out] и [in,out] интерфейсов COM, преимущества параметров out состоят в том, что вызывающим абонентам не нужно передавать предварительно выделенный объект в случаях, когда он не нужен вызываемым методом - это позволяет избежать как стоимости распределения, так и любых затрат, которые могут быть связаны с маршалингом (более вероятно, с COM, но не редкостью в .NET).

  • 3
    «В отличие от этого параметры ref считаются изначально назначенными вызываемым пользователем», вы наверняка имели в виду «вызывающий». Я пытался отредактировать ваш ответ, но он не позволил мне сохранить такие незначительные изменения.
  • 0
    Ссылка имеет очень четкое объяснение разницы, лучше, чем большинство ответов здесь. Спасибо!
82

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

  • ref означает, что параметр имеет значение на нем до, входящее в функцию. Вызываемая функция может читать и/или изменять значение в любое время. Параметр входит, затем выходит

  • out означает, что перед входом в функцию этот параметр не имеет официального значения. Вызываемая функция должна инициализировать его. Параметр выходит только

Здесь мой любимый способ взглянуть на него: ref - передать переменные по ссылке. out - объявить вторичное возвращаемое значение для функции. Как будто вы могли бы написать это:

// This is not C#
public (bool, string) GetWebThing(string name, ref Buffer paramBuffer);

// This is C#
public bool GetWebThing(string name, ref Buffer paramBuffer, out string actualUrl);

Здесь приведен более подробный список эффектов каждой альтернативы:

Перед вызовом метода:

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

out: метод вызова не требуется устанавливать значение аргумента перед вызовом метода. Скорее всего, вы не должны. Фактически любое текущее значение отбрасывается.

Во время вызова:

ref: вызываемый метод может прочитать аргумент в любое время.

out: вызываемый метод должен инициализировать параметр перед его чтением.

Удаленные вызовы:

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

out: ничто не передается удаленному вызову. Быстрее.

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

15

Пример для OUT: переменная получает значение, инициализированное после входа в метод. Позже это же значение возвращается в метод main.

namespace outreftry
{
    class outref
    {
        static void Main(string[] args)
        {
            yyy a = new yyy(); ;

            // u can try giving int i=100 but is useless as that value is not passed into
            // the method. Only variable goes into the method and gets changed its
            // value and comes out. 
            int i; 

            a.abc(out i);

            System.Console.WriteLine(i);
        }
    }
    class yyy
    {

        public void abc(out int i)
        {

            i = 10;

        }

    }
}

Выход:

10

===============================================

Пример для Ref: переменная должна быть инициализирована перед входом в метод. Позднее то же значение или измененное значение будет возвращено основному методу.

namespace outreftry
{
    class outref
    {
        static void Main(string[] args)
        {
            yyy a = new yyy(); ;

            int i = 0;

            a.abc(ref i);

            System.Console.WriteLine(i);
        }
    }
    class yyy
    {

        public void abc(ref int i)
        {
            System.Console.WriteLine(i);
            i = 10;

        }

    }
}

Выход:

    0
    10

=================================

Надеюсь, теперь все ясно.

9

Параметры Ref и Out:

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

Вы должны назначить значение для параметра out в кубе метода calee, иначе метод не будет скомпилирован.


Параметр Ref: Он должен быть инициализирован перед тем, как перейти к методу. Ключевое слово ref в параметре метода заставляет метод ссылаться на ту же переменную, которая была передана в качестве входного параметра для того же метода. Если вы внесете какие-либо изменения в переменную, они будут отражены в переменной.

int sampleData = 0; 
sampleMethod(ref sampleData);

Пример параметра Ref

public static void Main() 
{ 
 int i = 3; // Variable need to be initialized 
 sampleMethod(ref i );  
}

public static void sampleMethod(ref int sampleData) 
{ 
 sampleData++; 
} 

Исходный параметр: Не нужно инициализироваться перед тем, как перейти к методу. Параметр out может использоваться для возврата значений в той же переменной, которые передаются как параметр метода. Любые изменения, внесенные в параметр, будут отражены в переменной.

 int sampleData; 
 sampleMethod(out sampleData);

Ex out Out

public static void Main() 
{ 
 int i, j; // Variable need not be initialized 
 sampleMethod(out i, out j); 
} 
public static int sampleMethod(out int sampleData1, out int sampleData2) 
{ 
 sampleData1 = 10; 
 sampleData2 = 20; 
 return 0; 
} 

9
  • Перед тем, как передать его, необходимо инициализировать переменную A ref.
  • В реализации вашей функции должна быть указана переменная out.
  • out параметры могут рассматриваться как дополнительные возвращаемые переменные (не вводятся)
  • ref параметры могут рассматриваться как как входные, так и выходные переменные.
6

из

В С# метод может возвращать только одно значение. Если вы хотите вернуть более одного значения, вы можете использовать ключевое слово out. Модификатор out возвращается как обратная ссылка. Самый простой ответ заключается в том, что ключевое слово "out" используется для получения значения из метода.

  • Вам не нужно инициализировать значение в вызывающей функции.
  • Вы должны назначить значение в вызываемой функции, иначе компилятор сообщит об ошибке.

исй:

В С#, когда вы передаете тип значения, такой как int, float, double и т.д. в качестве аргумента параметра метода, он передается по значению. Поэтому, если вы изменяете значение параметра, это не влияет на аргумент в вызове метода. Но если вы отметите параметр ключевым словом "ref", он будет отображаться в фактической переменной.

  • Вам нужно инициализировать переменную до вызова функции.
  • Не обязательно назначать какое-либо значение параметру ref в методе. Если вы не изменяете значение, в чем состоит необходимость отметить его как "ref"?
4

out указывает, что параметр является выходным параметром, то есть он не имеет значения, пока он не будет явно установлен методом.

ref указывает, что значение является ссылкой, которая имеет значение и значение которого вы можете изменить внутри метода.

4

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

1

Параметр out - это параметр ref со специальным атрибутом Out(). Если параметр для метода С# объявлен как out, компилятор потребует, чтобы этот параметр был записан до того, как он может быть прочитан, и до того, как метод сможет вернуться. Если С# вызывает метод, параметр которого включает атрибут Out(), компилятор будет в целях принятия решения о том, следует ли сообщать об ошибках "undefined variable", притвориться, что переменная записывается непосредственно перед вызовом метода. Обратите внимание, что, поскольку другие языки .net не добавляют то же значение к атрибуту Out(), возможно, что вызов подпрограммы с параметром out оставит указанную переменную незатронутой. Если переменная используется как параметр out до того, как она определенно назначена, компилятор С# сгенерирует код, чтобы убедиться, что он очищается в какой-то момент до его использования, но если такая переменная уходит и возвращается в область видимости, не гарантируйте, что он будет очищен снова.

1

out параметры инициализируются методом, который называется, ref параметры инициализируются перед вызовом метода. Поэтому параметры out используются, когда вам просто нужно получить вторичное возвращаемое значение, параметры ref используются для получения значения и, возможно, возвращают изменение к этому значению (во-вторых, к основному возвращаемому значению).

1

Ключевое слово ref используется для передачи значений по ссылке. (Это не исключает, что переданные значения являются типами значений или ссылочными типами). Выходные параметры, указанные с ключевым словом out, предназначены для возврата значений из метода.

Одним из ключевых отличий в коде является то, что вы должны установить значение выходного параметра в этом методе. Это не относится к параметрам ref.

Подробнее см. http://www.blackwasp.co.uk/CSharpMethodParameters.aspx

0

out получил новый синтаксис succint в С# 7 https://docs.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7#more-expression-bodied-members и еще более увлекательным является усовершенствование кортежей С# 7, которое является более элегантным выбором, чем использование ref и out IMHO.

0

Они немного отличаются друг от друга.

Параметр out не должен быть инициализирован вызываемым пользователем перед передачей методу. Поэтому любой метод с параметром out

  • Невозможно прочитать параметр перед назначением ему значения
  • Обязательно присвойте ему значение перед возвратом

Это используется для метода, который должен перезаписывать свой аргумент независимо от его предыдущего значения.


Параметр

A ref должен быть инициализирован вызываемым пользователем, прежде чем передать его методу. Поэтому любой метод с параметром ref

  • Можно проверить значение перед его назначением
  • Может вернуть исходное значение, нетронутое

Это используется для метода, который должен (например,) проверять его значение и проверять его или нормализовать.

0

Когда параметр out объявляется в объявлении метода, тело метода должно назначить значение переменной out перед возвратом. Таким образом, ответственность вызываемого метода присваивает значение параметру out перед его возвратом.

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

0

out и ref являются точно такими же, за исключением того, что переменные не нужно инициализировать перед отправкой в ​​бездну. Я не настолько умный, я обрезал это из библиотеки MSDN:).

Однако, чтобы быть более явным в отношении их использования, значение модификатора заключается в том, что если вы измените ссылку на эту переменную в своем коде, out и ref вызовет изменение вашей вызывающей переменной. В приведенном ниже коде переменная ceo будет ссылкой на newGuy, как только она вернется с вызова на doStuff. Если бы не ref (или out), ссылка не была бы изменена.
private void newEmployee()
{
    Person ceo = Person.FindCEO();
    doStuff(ref ceo);
}

private void doStuff(ref Person employee)
{
    Person newGuy = new Person();
    employee = newGuy;
}
0

Этот Вывод и ref Paramerter в С# содержит несколько хороших примеров.

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

0

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

  • 1
    Foo (ref null) не скомпилируется, но строка bar = null; Foo (ссылка бар); Это хорошо.
  • 0
    Задохнуться от нулевой константы? Как Джеймс Керран, вы не можете передать константу в аргументе ссылки.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню