C # - Синтаксический сахар для выходных параметров? - PullRequest
8 голосов
/ 14 апреля 2009

Скажем на минуту, что C # допускает множественные возвращаемые значения в самом чистом смысле, где мы ожидаем увидеть что-то вроде:

string sender = message.GetSender();
string receiver = message.GetReceiver();

сжато до:

string sender, receiver = message.GetParticipants();

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

Аналогично, у нас есть что-то вроде этого, в настоящее время в C #:

string receiver;
string sender = message.GetParticipants(out receiver);

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

У меня вопрос: есть ли синтаксический сахар в текущем C #, который позволяет разработчику сделать это объявление в той же строке, что и вызов метода? Я думаю, что это сделало бы разработку (крошечную) более плавной, а также сделало бы код более читабельным, если бы я делал что-то вроде:

string sender = message.GetParicipants(out string receiver);

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

Ответы [ 10 ]

9 голосов
/ 14 апреля 2009

Нет, в настоящее время нет синтаксического сахара вокруг этого. Я не слышал ни о каком намерении представить что-либо.

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

5 голосов
/ 14 апреля 2009

.NET 4 будет добавлять концепцию Tuple, которая занимается этим. К сожалению, язык C # не будет обеспечивать никакой языковой поддержки для «destructuring bind».

4 голосов
/ 14 апреля 2009

Лично мне нравится неудобство, возникающее при использовании параметров. Это помогает мне думать о том, действительно ли мой метод делает то, что он должен быть, или я вложил в него слишком много функциональности. Тем не менее, возможно, динамическая типизация в C # 4.0 / .Net 4 решит некоторые ваши проблемы.

dynamic participant = message.GetParticipants();

var sender = participant.Sender;
var recipient = participant.Recipient;

, где

public object GetParticipants()
{
     return new { Sender = ..., Recipient = ... };
}
2 голосов
/ 16 апреля 2014

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

int.TryParse(s, out var x);
2 голосов
/ 14 апреля 2009

Где это меня больше всего беспокоит: поскольку нет перегрузки (скажем) DateTime.TryParse, которая не принимает параметр out, вы не можете написать

if (DateTime.TryParse(s, out d))
{
   return new ValidationError("{0} isn't a valid date", s);
}

без объявления d. Я не знаю, если это проблема с параметрами out или просто с тем, как реализован метод TryParse, но это раздражает.

2 голосов
/ 14 апреля 2009

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

В perl Вы можете назначить массив списку переменных в скобках. Так, например, вы можете сделать это

($user, $password) = split(/:/,$data);
2 голосов
/ 14 апреля 2009

Вы также можете вернуть Tuple<T,U> или что-то подобное. Однако, так как вы хотите вернуть две строки, это может сбить с толку.

Я использую структуры Tuples библиотеки BclExtras , что очень удобно (нашло это на SO, спасибо JaredPar!).

0 голосов
/ 14 апреля 2009

Я думаю, что это не то, что вы хотите. Возможно, вы столкнулись с фрагментом кода, где вы бы имели понравилось это. Но переменные появляются из ниоткуда, потому что они были введены в список параметров будет личный кошмар (для меня :))

Несколько возвращаемых значений имеют серьезные недостатки по сравнению с точкой портативности / ремонтопригодности. Если вы делаете функцию, которая возвращает две строки и теперь вы хотите, чтобы он вернул три, вам придется изменить весь код который использует эту функцию. Однако в таких распространенных сценариях тип возвращаемой записи обычно играет хорошо.

возможно, вы открываете ящик Пандоры; -)

Для линейного уплотнения:

string s1, s2; s1 = foo.bar(s2);

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

0 голосов
/ 14 апреля 2009

Попробуйте следующий код

Participants p = message.GetParticipants();
log(p.sender,p.receiver);
0 голосов
/ 14 апреля 2009

В лучшем случае вам придется использовать var вместо явного типа, если только вы не хотите ограничить все множественные возвращаемые значения одним и тем же типом (вряд ли это целесообразно). Вы также ограничивали бы область действия переменной; в настоящее время вы можете объявить переменную в более высоком объеме и инициализировать ее в параметре out. При таком подходе переменная выходит из области действия в том же блоке, что и ее назначение. Очевидно, что в некоторых случаях это применимо, но я бы не хотел применять это в качестве общего правила. Очевидно, что вы можете оставить опцию «out» на месте, но есть вероятность, что люди собираются писать код для одного или другого подхода.

...