Why does C# not allow me to call a void method as part of the return statement?

与世无争的帅哥 提交于 2019-11-30 07:51:40

Because it's simply the way the language is defined.

A method can use return statements to return control to its caller. In a method returning void, return statements cannot specify an expression. In a method returning non-void, return statements must include an expression that computes the return value.

It's an arbitrary decision (presumably made for compatibility with ANSI C and its other descendants), and other languages do things differently.

For example, in Python, all functions return a value. If you execute a return statement without a value, or let control reach the end of the function, then it's just like you had written return None.

In contrast, Pascal limits the terminology of function to subprograms that have a return value; if you don't want to return anything, you use a procedure instead.

void is the absence of information; it doesn’t make any sense to return it. It’s not a type*, and it’s not a value, unlike in some other languages. No, that’s not really a limitation.

* Well, sort of, as @Lucas points out. It’s an informational type; it doesn’t actually represent a type in the usual sense. You can’t have one.

Your question is pretty much about the difference between the void type and the unit type (most commonly seen in functional languages like F#).

Basically, void is not a real type. While there is System.Void for reflection purposes, you can't use void in most places where you can use a real type: you can't have a variable of type void and you can't use it in generics (even though being able to write Func<void> would be sometimes very useful).

On the other hand, unit in F# is a real type: it has a (single) value (called ()), you can write the equivalent of Func<void> (written unit -> unit, where the first unit means “no parameters”, similar to writing void in the parameter list in C) and you can have variables of type unit. For example:

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

The last line actually shows that in F#, you sometimes have to explicitly return unit.

This is not allowed according to the language specification. From 15.9.4 of ECMA-334 (emphasis mine):

A return statement with an expression can only be used in a function member that computes a value, that is, a method with a non-void return type, the get accessor of a property or indexer, or a user-defined operator.

It comes down to choices by the language designer.

From a type perspective, void has no enumerable values, so it doesn't make sense to return a value of "void" type? void is absence of type or evaluation context.

You cannot instantiate or return "void" in C# or Java.

If you could do so, then you should also be able to say:

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

The above doesn't make any sense, but is equivalent to what you propose.

In the end, proposing that we could propagate void return context with the return statement is simply a matter of syntactical sugar, which comes down to choices made by the language designer.

The C# language spec http://msdn.microsoft.com/en-us/library/aa691305(v=vs.71).aspx (section 7.1) says

Nothing. This occurs when the expression is an invocation of a method with a return type of void. An expression classified as nothing is only valid in the context of a statement-expression (Section 8.6).

On the otherhand, the C++ designer actually chose to allow just the construct you propose, but it was specifically for syntactical uniformity in templates. In C++ the return type of a template function can be a template parameter. (Stroustrop C++ Programming Language p 148) Without it, there would be common cases that would compile for all types, but not for void, such as nested function calls of type T. For that reason, the following is valid 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();

So the statement expression "return B();" where B is a void function is only a shortcut for "B(); return;" and doesn't actually yield a value, because there is no such thing as a void value.

I have a guess about a legitimate reason for this.

When the compiler sees an expression, it tries to match it to something from a list of known expressions. You could say that there are two kinds of statements that start with return:

  1. return expr where expr is an expression assignable to the declared return type of the containing method
  2. return without anything else

These are entirely different statements, even if they look similar. But one can compile to the other, in certain cases (just like foreach compiles to a while plus stuff). So, you could add a rule that says that return expr compiles to whatever expr; return; compiles to, whenever expr is determined to be of no return type (that is, void).

But then, the implementers of C# compilers would have to allow for all expressions to have no return type, when normally only statements are allowed to have no return type. If they did this, then they would have to manually disallow expressions of no type wherever an actual type is required. For example, in the expressions that act as arguments to a function call MyMethod(1, 2, SomethingVoid()), the compiler would additionally have to check whether any of these expressions does not return a type. And for every new kind of expression added to C# in the future, the same check would have to be added.

The above is possible, but it would happen for no reason other than to allow non-statement expressions in the abstract syntax tree (that's generated during compilation) to have no return type, and that would be the case just to allow for a minor syntactic structure - and one that has an alternative which is no longer (in keystrokes) to type and possibly clearer to read.

In the end, it doesn't sound like it's worth it.

You're actual question title doesn't appear to be covered by the answers, although they may be getting at the correct thing. You're question title

Why does C# not support returning a method with a void return type

Actually C# does allow this, just not in the format you're trying. Using the void keyword as others have answered means that the method returns nothing. If you want to return a method, that returns nothing then you want to do something like this:

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

Then a simple call will give you this action:

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

A void is empty. The void keyword in the C# language indicates that a method returns nothing. When a void method is invoked, it has no result and no variable can be assigned.

see this explanation

Correct me if i am wrong but i think its because:

public void MethodA() 
{ 
    return; 
}

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

would be the same like(which are legal):

public void MethodA() 
{ 

}

public void MethodB() 
{
    MethodA();
}

And also:

public void MethodMeh() 
{
    if (expression) 
    {
        MethodA();
    }else{
    // do more stuff
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!