Почему мне нужно использовать ключевое слово ref как в декларации, так и в Call? - PullRequest
6 голосов
/ 06 октября 2009

Дубликат: Какова цель ключевого слова «out» у звонящего?

Почему Мне нужно использовать ключевое слово 'ref' в объявлении и вызове.

void foo(ref int i)
{

}

Например, рассмотрим функцию выше. Если я назову это без ключевого слова ref как

foo(k);

это даст мне ошибку:

Аргумент '1' должен быть передан с ключевое слово ref

Почему недостаточно просто указать только сигнатуру метода?

Ответы [ 6 ]

12 голосов
/ 06 октября 2009

Это потому, что ref указывает, что параметр должен быть передан по ссылке. Это что-то вроде указателя в C ++

Например;

void CalFoo()
{
  var i=10;
  foo(ref i);  //i=11
}
void foo(ref int i)
{
   i++;
}

но

void CalFoo()
{
  var i=10;
  foo(i);  //i=10
}
void foo(int i)
{
   i++;
}

Я думаю, вы можете иметь foo(ref int) и foo(int) в одном классе. Так что если вы не укажете ref .. как компилятор узнает, какой из них вызвать?

9 голосов
/ 06 октября 2009

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

4 голосов
/ 06 октября 2009

(Как уже упоминалось, это обман этот вопрос .)

Во-первых, он используется как часть перегрузки метода:

public void Foo(string x) { ... }
public void Foo(ref string x) { ... }

...

string x = "";
Foo(x); // Which should be used if you didn't have to specify ref?

Теперь одним из ответов может быть запрет такого рода перегрузки ... но я думаю, что для C # было бы хорошо требовать это на стороне вызывающего в качестве документации:

  • Поведение значительно меняется при использовании ref (или out)
  • Вызывая редкие случаи использования ref / out, это означает, что вам никогда не нужно проверять аргумент передается по значению или ссылке
  • Это также влияет на то, что вы можете передать (например, вы не можете передать литерал или результат вызова метода). Это яснее, когда это явно.

Обратите внимание, что C # 4 допускает неявное использование ref для методов COM, поскольку существует очень много ref параметров, которые не действительно имеют поведение ref (или, по крайней мере, они не воспользоваться этим). В таких случаях компилятор вводит новую локальную переменную, чтобы с точки зрения вызывающей стороны аргумент был передаваемым по значению:

ComMethod(x);

переводится в:

MyType tmp = x;
ComMethod (ref tmp);

Это хороший компромисс для методов COM, но я рад, что это не так для обычного управляемого кода.

3 голосов
/ 06 октября 2009

Хотя ref в большинстве случаев может быть выведено из сигнатуры метода, оно всегда обязательно из-за того, что оно может изменить поведение кода после полного вызова метода. Рассмотрим:

string hello = "world";
MyMethod(ref hello);
Console.WriteLine(hello);

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

3 голосов
/ 06 октября 2009

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

1 голос
/ 06 октября 2009

Я также слышал (или читал где-то - возможно, это было в интервью с разработчиками языка), что причина (как и для многих других «функций» в C #) состоит в том, чтобы напомнить программисту, что функция, которую он должен вызвать используйте аргумент по ссылке.

...