2016-08-25 3 views
2

Мне просто интересно ... Почему C# не допускает множественные возвращаемые значения?Почему C# не допускает множественные возвращаемые значения?

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

static void Check(MyTask task) 
{ 
    if (GoodReasonsNotTo(task)) 
    { 
     throw new ApplicationException("There are good reasons not to do this."); 
    } 
} 

public static int UglyDo(MyTask task, out string response) 
{ 
    Check(task); 
    //... 
    response = "Done"; 
    return 7; 
} 

static void Main(string[] args) 
{ 
    var task = new MyTask("Add multiple return values"); 

    string response; 
    var err = UglyDo(task, out reponse)); 
} 

Код выше может быть выражена по-разному:

static void Check(MyTask task) 
{ 
    if (GoodReasonsNotTo(task)) 
    { 
     throw new ApplicationException("There are good reasons not to do this."); 
    } 
} 

public static (int, string) PrettyDo(MyTask task) 
{ 
    Check(task); 
    //... 
    return 7, "Done."; 
} 
static void Main(string[] args) 
{ 
    var task = new MyTask("Add multiple return values"); 

    var (err, response) = PrettyDo(task); 
} 

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

Кроме того, может ли он поддержать его в будущем?

BTW. Синтаксис синтаксиса StackOverflow имеет дело с этим красиво - это, безусловно, означает, что это будет хорошо.

+0

Я думаю, что язык программирования Go на самом деле имеет это. – EJoshuaS

+0

Возможно, потому, что существуют другие способы достижения того же, например. используйте небольшой класс с 2 членами или Tuple <>. Все эти новые вещи делают C# труднее читать для людей, которые, например, имеют фон C++. –

ответ

8

Забавный, что вы просите. Было только что объявлено, что оно will be supported in C# 7.0 [MSDN]

+0

Удивительная ссылка, спасибо.Хотя разрешение на вернувшиеся кортежи на самом деле не является реальной сделкой. Бит .Item1 является уродливым. – mayu

+0

@Tymski Если вы использовали C# 7, это было в лучшем случае предварительным просмотром. Не стесняйтесь сообщать об ошибке или вносить свой вклад в обсуждение github: https://github.com/dotnet/roslyn/issues/347. Уничтожение (так вам не нужно .Item1 и т. Д.), Как и на других языках. –

+1

Я бы не сказал, что это было «просто» объявлено, это было в планах C# 7 в течение нескольких месяцев. – DavidG

1

Я все еще новичок в C#, но не поможет ли вам такое обходное решение? Создайте новый класс с требуемыми параметрами и создайте функцию, возвращающую этот класс.

public static testClass PrettyDo(MyTask task) 
{ 
    Check(task); 
    //... 
    testClass answer = new testClass(); 

    answer.param1 = 7; 
    answer.param2 = "Done."; 

    return answer; 
} 

public class testClass 
{ 
    public int param1 { get; set; } 
    public string param2 { get; set; } 
} 
+1

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

2

Хороший вопрос. В настоящее время это поддерживается некоторыми языками более высокого уровня (например, Go), а также, по крайней мере, некоторыми языками ассемблера, такими как MIPS, для которых reserves several registers для аргументов, а также для двух значений возврата (но это, по меньшей мере, частично соглашение, а не некоторые фактическое физическое различие между регистрами). В этом более общем смысле нет ничего особо «особого» о возвращаемых значениях.

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

Edit: Прямо сейчас ближе мы добираемся до нескольких возвращаемых значений, вероятно, кортежи, которые, к сожалению, имеют очень неудобный синтаксис в C# прямо сейчас (они гораздо более удобны для использования в некоторых других языках .NET, в частности F # , что я действительно хотел бы получить больше внимания, но это только мое мнение, я думаю). По-видимому, они смотрят на улучшение этого в будущих версиях C#, которые могут быть как можно ближе к концу (что, я полагаю, согласуется с моим подозрением, что все, что они делают с точки зрения множественных возвращаемых значений, будет просто быть синтаксическим сахаром для объекта).

+1

Синтаксический сахар был бы достаточно хорош! – mayu

1

Как об использовании Tuple:

public static Tuple<int, string> PrettyDo(MyTask task) 
{ 
    Check(task); 
    //... 
    return Tuple.Create(7, "Done."); 
} 
static void Main(string[] args) 
{ 
    var task = new MyTask("Add multiple return values"); 

    var result = PrettyDo(task); 
    var err = result.Item1; 
    var response = result.Item2; 
} 

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

+0

Я должен был упомянуть об этом, мой вопрос скорее скорее вопрос дизайна, чем попытка найти способ его достижения. +1 В любом случае :) – mayu

Смежные вопросы