I am curious if there is a legitimate reason as to why C# does not support calling a void method as part of the return statement when the calling method's return type is also void.
public void MethodA()
{
return;
}
public void MethodB()
{
return MethodA();
}
So we would normally see this:
public void MethodMeh()
{
if (expression)
{
MethodA();
return;
}
// Do more stuff
}
... when we could be using this instead:
public void MethodAwesome()
{
if (expression)
return MethodA();
// Do more stuff
}
Is this a language limitation due to how C# handles void?
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 returningvoid
,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
:
return expr
whereexpr
is an expression assignable to the declared return type of the containing methodreturn
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
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.
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
}
}
来源:https://stackoverflow.com/questions/24665649/why-does-c-sharp-not-allow-me-to-call-a-void-method-as-part-of-the-return-statem