Когда использовать в отношении refs vs out - PullRequest
362 голосов
/ 04 октября 2009

Кто-то спросил меня на днях, когда им следует использовать ключевое слово параметра out вместо ref. Хотя я (я думаю) понимаю разницу между ключевыми словами ref и out (об этом спрашивали до ), и лучшим объяснением этого является то, что ref == in и out, каковы (гипотетические или кодовые) примеры, в которых я должен всегда использовать out, а не ref.

Поскольку ref является более общим, почему вы хотите использовать out? Это просто синтаксический сахар?

Ответы [ 16 ]

5 голосов
/ 04 октября 2009

Просто для пояснения в комментарии OP о том, что использование ref и out является «ссылкой на тип значения или структуру, объявленную вне метода», которая уже была установлена ​​неверно.

Рассмотрим использование ref для StringBuilder, который является ссылочным типом:

private void Nullify(StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// Hi Guy

Применительно к этому:

private void Nullify(ref StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(ref sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// NullReferenceException
4 голосов
/ 05 февраля 2017

Дополнительные примечания относительно C # 7:
В C # 7 нет необходимости предварительно объявлять переменные, используя out. Итак, такой код:

public void PrintCoordinates(Point p)
{
  int x, y; // have to "predeclare"
  p.GetCoordinates(out x, out y);
  WriteLine($"({x}, {y})");
}

Можно записать так:

public void PrintCoordinates(Point p)
{
  p.GetCoordinates(out int x, out int y);
  WriteLine($"({x}, {y})");
}

Источник: Что нового в C # 7.

4 голосов
/ 28 октября 2016

Как правило, ref и out для передачи объекта / значения между методами

Ключевое слово out вызывает передачу аргументов по ссылке. Это похоже на ключевое слово ref, за исключением того, что ref требует инициализации переменной перед ее передачей.

out: Аргумент не инициализирован и должен быть инициализирован в методе

ref: Аргумент уже инициализирован, и его можно прочитать и обновить в методе.

Какая польза от «ref» для ссылочных типов?

Вы можете изменить данную ссылку на другой экземпляр.

Знаете ли вы?

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

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

    • Асинхронные методы, которые вы определяете, используя модификатор async.
    • Методы итератора, которые включают в себя возврат доходности или оператор доходности.
  3. Свойства не являются переменными и поэтому не могут быть переданы в качестве параметров.

4 голосов
/ 18 марта 2016

почему ты хочешь использовать?

Чтобы другие знали, что переменная будет инициализирована, когда она вернется из вызванного метода!

Как упомянуто выше: «для параметра out вызывающему методу требуется присвоить значение, прежде чем метод вернет

пример:

Car car;
SetUpCar(out car);
car.drive();  // You know car is initialized.
4 голосов
/ 29 июня 2014

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

0 голосов
/ 10 апреля 2019

Следует отметить, что in является действительным ключевым словом на C # ver 7.2 :

Модификатор параметра in доступен в C # 7.2 и более поздних версиях. Предыдущие версии генерировали ошибку компилятора CS8107 («Функция« ссылки только для чтения »недоступна в C # 7.0. Пожалуйста, используйте языковую версию 7.2 или выше».) Чтобы настроить языковую версию компилятора, см. Выбор версии языка C #.

...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...