Зачем использовать ключевое слово вместо присваивания в C #? - PullRequest
3 голосов
/ 03 мая 2011

Я исследовал ключевое слово out в C # после прочтения раздела об этом в C # в Depth.Я не могу найти пример, который показывает, почему ключевое слово требуется, а не просто присвоение значения оператора возврата.Например:

public void Function1(int input, out int output)
{
    output = input * 5;
}

public int Function2(int input)
{
    return input * 5;
}

...
int i;
int j;

Function1(5, out i);
j = Function2(5);

И i, и j теперь имеют одинаковое значение.Это просто удобство возможности инициализации без знака = или есть какое-то другое значение, которое я не вижу?Я видел несколько похожих ответов, в которых говорилось, что ответственность за инициализацию переносится на вызываемого здесь Но все это дополнительно вместо того, чтобы просто присваивать возвращаемое значение и не иметь подписи метода void?

Ответы [ 7 ]

13 голосов
/ 03 мая 2011

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

Хороший пример - Int32.TryParse(input, out myVar), он вернет true, если он был успешным иложь в противном случае.Вы можете получить преобразованное int через параметр out.

int myOutVar;

if (Int32.TryParse("2", out myOutVar))
{
   //do something with the int
}else{
    //Parsing failed, show a message
}
3 голосов
/ 03 мая 2011

Много раз, использование out может помочь с небольшим приростом производительности.

Рассмотрим метод TryGetValue для IDictionary (скажем, myDictionary является IDictionary<string, string>) Вместо того, чтобы делать это:

string value = String.Empty;
if (myDictionary.ContainsKey("foo"))
{
  value = myDictionary["foo"];
}

И ContainsKey, и индексатор должны искать ключ в словаре, но вы можете избежать этого двойного поиска в положительном случае, выполнив:

string value;
if (!myDictionary.TryGetValue("foo", out value))
{
  value = String.Empty;
}

ИМО, это достойная причина для использования out параметров.

3 голосов
/ 03 мая 2011

Ключевые слова out / ref в C # следует использовать только тогда, когда вам нужно вернуть несколько значений. Даже тогда вы должны сначала рассмотреть возможность использования типа контейнера (например, Tuple) для возврата нескольких значений, прежде чем вернуться к out / ref. Всякий раз, когда вы возвращаете одно значение, оно должно быть просто возвращено.

2 голосов
/ 03 мая 2011

К сожалению, мы не можем сделать что-то вроде ниже в C #:

a,b = func(x,y,z);

то, что мы делаем на Python или других языках. отчасти преодолевает это.

F # преодолел это с помощью кортежей, которые я считаю.

PS: возврат нескольких значений из функции может быть не всегда удачным. Крошечные типы хороши в большинстве случаев - http://www.martinfowler.com/bliki/DataClump.html

1 голос
/ 03 мая 2011

В основном вы делаете что-то вроде (моя база данных прочитана)

if (ReadSingle<UserRecord>(cmd, out user))
    Cache.Insert(cacheId, user, null,
        DateTime.MaxValue, TimeSpan.FromMinutes(3));

Или вы делаете что-то вроде:

user = ReadSingle<UserRecord>(cmd);
if(null != user)
   // Cache.Insert ...

Это немного упрощает код для использования логического результата (что запись была прочитана из базы данных) и получения фактической записи в переменную через ключевое слово out.

1 голос
/ 03 мая 2011

Некоторые из них для ясности. Возьмите методы TryParse (), например

Int32.TryParse("3", out myInt);

Возвращает bool, который указывает, была ли строка может быть проанализирована в int. Если бы вы только что

Int32.TryParse("3", myInt);

Что происходит, когда это называется? Назначен ли myInt? TryParse возвращает int?

Это не совсем очевидно. Но если у меня есть параметр out, то я знаю, что значение присваивается, и что возвращение - это что-то другое.

1 голос
/ 03 мая 2011

Например, Int32.TryParse возвращает логическое значение, если оно было проанализировано правильно, а параметр out изменяет значение. Если проанализированное значение равно 0 и оно возвращает true, это означает, что значение, которое вы отправили для анализа, было 0. Если он возвращает false, то синтаксический анализатор завершился ошибкой.

...