Почему С# не позволяет мне вызвать метод void как часть оператора return?

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

public void MethodA() 
{ 
    return; 
}

public void MethodB() 
{
    return MethodA();
}

Итак, мы обычно видим это:

public void MethodMeh() 
{
    if (expression) 
    {
        MethodA();
        return;
    }

    // Do more stuff
}

... когда мы могли бы использовать это вместо:

public void MethodAwesome() 
{
    if (expression) 
        return MethodA();

    // Do more stuff
}

Является ли это языковым ограничением из-за того, как С# обрабатывает void?

Ответ 1

Потому что это просто способ язык определен.

Метод может использовать операторы return, чтобы вернуть управление своему вызывающему. В методе, возвращающем void, операторы return не могут указывать выражение. В методе, возвращающем не void, операторы return должны включают выражение, которое вычисляет возвращаемое значение.

Это произвольное решение (предположительно сделанное для совместимости с ANSI C и его другими потомками), а другие языки выполняют разные вещи.

Например, в Python все функции возвращают значение. Если вы выполняете инструкцию return без значения, или пусть управление достигает конца функции, тогда оно точно так же, как вы написали return None.

Напротив, Pascal ограничивает терминологию function подпрограммами, которые имеют возвращаемое значение; если вы ничего не хотите возвращать, вместо этого используйте procedure.

Ответ 2

void - отсутствие информации; он не имеет никакого смысла возвращать его. Это не тип *, а его не значение, в отличие от некоторых других языков. Нет, на самом деле это не ограничение.

* Ну, вроде, как указывает @Лукас. Его информационный тип; он фактически не представляет тип в обычном смысле. У вас не может быть этого.

Ответ 3

Ваш вопрос в значительной степени связан с разницей между типом void и тип unit (чаще всего это видятся на функциональных языках, таких как F #).

В принципе, void не является реальным типом. Хотя для целей размышления System.Void, вы не можете использовать void в большинстве мест, где вы можете использовать реальный тип: вы можете 't имеет переменную типа void, и вы не можете использовать ее в generics (хотя возможность писать Func<void> иногда очень полезна).

С другой стороны, unit в F # является реальным типом: он имеет (одно) значение (называемое ()), вы можете записать эквивалент Func<void> (записано unit -> unit, где первый unit означает "без параметров", аналогично записи void в списке параметров в C), и вы можете иметь переменные типа unit. Например:

let unitTest (f : unit -> unit) =
    let nothing : unit = f()
    ()

Последняя строка фактически показывает, что в F # вам иногда нужно явно возвращать unit.

Ответ 4

Это зависит от выбора дизайнера языка.

С точки зрения типа void не имеет перечислимых значений, поэтому нет смысла возвращать значение типа "void"? void - это отсутствие типа или контекста оценки.

Вы не можете создавать или возвращать "void" на С# или Java.

Если вы можете это сделать, тогда вы также сможете сказать:

 void i;
 i = (what would go here?)
 return i;

Вышеприведенное не имеет никакого смысла, но эквивалентно тому, что вы предлагаете.

В конце концов, предлагая, чтобы мы могли распространять контекст void return с оператором return, это просто вопрос синтаксического сахара, который сводится к выбору, сделанному разработчиком языка.

Спецификация языка С# http://msdn.microsoft.com/en-us/library/aa691305(v=vs.71).aspx (раздел 7.1) говорит

Ничего. Это происходит, когда выражение является вызовом метода с возвращаемым типом void. Выражение, классифицированное как ничего, действует только в контексте выражения-оператора (раздел 8.6).

С другой стороны, разработчик С++ фактически решил разрешить только конструкцию, которую вы предлагаете, но она была специально для синтаксической однородности в шаблонах. В С++ возвращаемым типом функции шаблона может быть параметр шаблона. (Stroustrop С++ Programming Language p 148) Без него будут распространяться общие случаи, которые будут компилироваться для всех типов, но не для void, таких как вложенные вызовы функций типа T. По этой причине допустимо следующее: C + +:

void B() {
  return;
}

void A() {
  return B(); // legal C++ - doesn't yield a value
}

// But even in C++ the next line is illegal
int i = A();

Таким образом выражение выражения "return B();" где B - функция void, является только ярлыком для "B(); return;" и на самом деле не дает значение, потому что нет такой вещи, как значение void.

Ответ 5

Это запрещено в соответствии со спецификацией языка. Из 15.9.4 ECMA-334 (основное внимание):

Оператор return с выражением может использоваться только в члене функции, который вычисляет значение, которое is, метод с не-void возвращаемым типом, get accessor свойства или индексатора или определяемый пользователем Оператор.

Ответ 6

У меня есть предположение о законной причине.

Когда компилятор видит выражение, он пытается сопоставить его с чем-то из списка известных выражений. Можно сказать, что есть два типа операторов, начинающихся с return:

  • return expr где expr - выражение, назначаемое объявленному типу возвращаемого метода
  • return без каких-либо других

Это совершенно разные утверждения, даже если они выглядят одинаково. Но можно скомпилировать другой, в некоторых случаях (так же, как foreach компилируется в while плюс материал). Таким образом, вы можете добавить правило, в котором говорится, что return expr скомпилируется для компиляции expr; return;, когда expr определяется, что он не имеет типа возврата (т.е. void).

Но тогда, разработчики компиляторов С# должны были бы разрешить всем выражениям не иметь типа возврата, когда обычно только утверждениям не разрешен тип возврата. Если они это сделают, тогда им придется вручную запрещать выражения типа "тип", где требуется фактический тип. Например, в выражениях, которые выступают в качестве аргументов вызова функции MyMethod(1, 2, SomethingVoid()), компилятору дополнительно необходимо проверить, не возвращает ли какое-либо из этих выражений тип. И для каждого нового вида выражения, добавленного в С# в будущем, нужно добавить ту же проверку.

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

В конце концов, это не похоже, что это того стоит.

Ответ 7

Фактическое название вопроса, по-видимому, не подлежит рассмотрению ответами, хотя они могут получить правильную вещь. Заголовок вопроса

Почему С# не поддерживает возврат метода с типом возвращаемого типа

На самом деле С# разрешает это, просто не в том формате, который вы пытаетесь. Использование ключевого слова void, как ответили другие, означает, что метод ничего не возвращает. Если вы хотите вернуть метод, который ничего не возвращает, вы хотите сделать что-то вроде этого:

public Action MethodExample()
{
    return () => { Console.WriteLine("Hello World!"); };
}

Тогда простой вызов даст вам следующее действие:

var action = MethodExample();
action(); // prints Hello World

Ответ 8

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

см. это объяснение

Ответ 9

Исправьте меня, если я ошибаюсь, но я думаю, потому что:

public void MethodA() 
{ 
    return; 
}

public void MethodB() 
{
    return MethodA();
}

будет таким же, как (что является законным):

public void MethodA() 
{ 

}

public void MethodB() 
{
    MethodA();
}

А также:

public void MethodMeh() 
{
    if (expression) 
    {
        MethodA();
    }else{
    // do more stuff
    }
}