39

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?

Matt Beckman
  • 5,022
  • 4
  • 29
  • 42
  • 4
    I'm sure it's in the language spec. It would be very misleading to allow the return keyword in a context where no value is returned. – Eric J. Jul 10 '14 at 00:17
  • 3
    its like saying - "in this method which does not return a value,lets return this method(which also does not return)...and so on,and on..." – terrybozzio Jul 10 '14 at 00:22
  • 35
    None of the above examples returns a method! –  Jul 10 '14 at 07:54
  • may be compiler always looks for a ";" followed by `return` keyword in case of `void` return type, nothing else !!! (Its a guess. I am a java dev) – Not a bug Jul 10 '14 at 10:05
  • There is nothing inherent that would make this impossible. For example F# has the `Unit` type. The CLR has this very special void construct (inherited from C). To me it seems the C languages are the odd ones here. – usr Jul 10 '14 at 10:12
  • 5
    Why would you want to do MethodAwesome? Shorter code is not better code, clearer code is better code. It looks like it returns a method when it wouldn't be, that is unnessarily confusing. – JamesRyan Jul 10 '14 at 10:13
  • 6
    +1. Actually, this question could be extended to "why is it not legal to write `return void;` in a method returning a void?". And then, by extension, `return f()` if `f`'s return type is `void`. The problem I see - which may actually imply the answer to the question - is that it may lead to the question "Then why is it not legal to write a variable declaration like `void x = f()`?". – CompuChip Jul 10 '14 at 14:12
  • There's another flaw with an implementation of the suggested syntax. You're using `return` with a method that returns `void`, in a context that expects a value. So it would *only be usable* in the circumstance where you're in a `void` method and calling another `void` method. Otherwise it'd have to be a compiler error. Then later, if either one got changed to not be `void`, this syntax would break - whereas the usual syntax would continue working just fine. – Bobson Jul 10 '14 at 15:51
  • @BrianDrummond - I believe I've added the only answer that actually illustrates that the title asks. – Ian Jul 10 '14 at 16:14
  • @BrianDrummond Right. If you have a suggestion for a better title, edit away. "Why does C# not support returning the non-existent result of a method that has a void return type"? – Matt Beckman Jul 10 '14 at 17:49
  • @CompuChip I do think that might be a better title. – Matt Beckman Jul 10 '14 at 17:56
  • Lemme know if that question is better; I tried not to get into the details of 'void is not a real type' since that is essentially answering its own question :) – Michael Edenfield Jul 10 '14 at 21:15
  • @Bobson how is that any different from a method that returns a real type calling another method that returns the same type? – Michael Edenfield Jul 10 '14 at 21:16
  • Because it would be confusing to anybody reading the code, and it would only save you a few keystrokes anyway. Shorter isn't always better. – Harry Johnston Jul 11 '14 at 05:38
  • @MichaelEdenfield - Implicit casts. If I have a method that returns `IEnumerable`, which calls one which returns `IEnumerable`, and I later change the inner one to `List`, I don't need to do anything. If I change it to `Dictionary`, then I would need to change it, but that would be *expected* because everything that was calling this method to get a `IEnumerable` now gets new data. However, changing from `void` to any other return type *shouldn't* break anything, because nothing uses a `void`. – Bobson Jul 11 '14 at 14:58
  • @Bobson C# allows me to call a value-returning method and ignore the return type; *if* this silly "return void" syntax were legal, it would be easy enough to simply discard the newly-valid return type of the inner method if the outer method was void. – Michael Edenfield Jul 11 '14 at 15:00
  • @MichaelEdenfield - It's true, but then you lose the compiler error when you have `return true;` at the end of your `void` method. Calling a method and ignoring the return is simply a message, not even a warning, IIRC. – Bobson Jul 11 '14 at 18:07
  • Because in `C#` `return void;` is also invalid. – Tengyu Liu Jul 18 '14 at 21:12

9 Answers9

39

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.

dan04
  • 87,747
  • 23
  • 163
  • 198
28

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.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Aren't we already returning ``void`` when we use ``return;`` inside of a method that has a ``void`` return type? – Matt Beckman Jul 10 '14 at 00:20
  • 3
    @MattBeckman: No, you’re just returning. VB.NET makes this distinction clearer. – Ry- Jul 10 '14 at 00:21
  • @MattBeckman, note that `return` without an expression afterwards is not valid for a method with a return type. Clearly it returns nothing. – BradleyDotNET Jul 10 '14 at 00:22
  • Aye, but we're returning nothing. But isn't "nothing" the same as "absence of information" or "void"? – Matt Beckman Jul 10 '14 at 00:23
  • @MattBeckman: There are probably a bunch of situations where this doesn’t quite work, but I’d say “returning nothing” is returning `null`, and you just plain return (or exit) from void functions. – Ry- Jul 10 '14 at 00:24
  • 5
    In C++, it's really a limitation in templated scenarios, so it's allowed in those cases. The `unit` type with only a single value instead of `void` would've been a better solution, of course—the resulting code would've been completely the same. – Joker_vD Jul 10 '14 at 06:40
  • @LucasTrzesniewski is it really a type, or is System.Void just a type meant to represent void for reflection purposes. – NPSF3000 Jul 10 '14 at 14:32
  • @NPSF3000 It is a type primarily meant for reflection purposes. You can't instantiate it from C#, you cannot even write `typeof(System.Void)` (you have to write `typeof(void)` instead). You can't use `Activator.CreateInstance` to instantiate it. You can't use `Expression.New` to instantiate it either. I didn't try with IL emit. But you *can* use `FormatterServices.GetUninitializedObject` to get an instance of it. :) – Lucas Trzesniewski Jul 10 '14 at 14:42
  • Sure it makes sense. It's not like you suddenly have something to return, the called function returns nothing, and you're returning that, so you're returning nothing. – harold Jul 10 '14 at 15:41
  • F#'s approach is nice. It's equivalent, called unit and represented by `()`, is as value and type in and of itself (though it usually gets compiled to `void`), and you can event bind it to variables. There also aren't functions/methods that take no arguments; instead, they accept `unit`. – Jwosty Jul 10 '14 at 18:57
  • It's certainly a type in usual type theory - what's your argument that it wouldn't be? Sure you can only have one, but does that mean that a singleton also isn't a type? More expressive type systems (eg ML type ones) than the Java crop also pretty much all have it, the only reason to consider it special is because most people are used to rather limited type systems. In those systems sooner or later (usually when generics are involved) someone invents a escape hatch to patch the underlying weakness.. `Void` in Java, the special rules in C++ for templates,.. – Voo Jul 10 '14 at 20:28
  • @Voo: No, if you could only have one, it would be a type, but you *can’t* have a void at all. Haskell, F#, etc.’s `()` is nice for sure, but I don’t think it’s a limitation of C# regardless, especially since you don’t have to be able to pass a void around to make for clean code. – Ry- Jul 10 '14 at 21:19
  • @LucasTrzesniewski: `typeof(System.Void)` doesn’t make sense for any type, does it? – Ry- Jul 10 '14 at 21:21
  • @false Sure it's not a type in C# (otherwise we wouldn't have the discussion) but the *idea* of "returns nothing" can be perfectly represented in a type system. The problem with `void` as in Java, C++ or C# is that you run into limitations as soon as generics come into play. That's why C# needs both `Action` and `Function` delegates, why C++ needs special rules for when it's fine to `return void` (implicitly) in templates, and why Java got `Void` (which is basically just `unit`). – Voo Jul 10 '14 at 21:24
  • @Voo: Ah, okay. When you said “it's certainly a type in usual type theory”, I thought you were talking about C#’s `void`. (It’s what I’m referring to as well when saying it’s not a type.) The difference between `Action` and `Func` is a good point. – Ry- Jul 10 '14 at 21:28
  • @false For me `typeof(System.Void)` should make just as much sense as `typeof(void)`. After all, `typeof(void).FullName == "System.Void"`. I see `System.Void` as the *null object* for reflection purposes. – Lucas Trzesniewski Jul 10 '14 at 21:44
  • @LucasTrzesniewski: It’s not. It’s the non-type of the void non-object. `typeof(void)` gets you the type of void; you can’t get the type of a type. – Ry- Jul 10 '14 at 22:03
  • @false Hmm I see your point. I guess there's no definite answer there... Oh, and BTW, the type of a type is `System.Type` ;) – Lucas Trzesniewski Jul 10 '14 at 22:10
7

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.

svick
  • 236,525
  • 50
  • 385
  • 514
  • 2
    `Func` is also called `Action` :) – Luaan Jul 11 '14 at 08:53
  • @Luaan That's exactly the problem. It would be nice if methods like `Task.Factory.StartNew()` didn't have to have separate overloads for `Func` and for `Action`. – svick Jul 11 '14 at 09:36
  • Well, that would have to extend through a lot of the infrastructure too - e.g. `Task` etc. It nicely shows that C# wasn't much of a functional language in the beginning. Now it has to keep backward compatibility while introducing many functional paradigms :) – Luaan Jul 11 '14 at 09:44
4

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.

AlexD
  • 32,156
  • 3
  • 71
  • 65
4

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.

codenheim
  • 20,467
  • 1
  • 59
  • 80
  • 3
    What would go there? An expression of type `void`, of course. Like a call to a `void` function. Now, I can't see why assigning a `void` to a variable would ever be *useful*, but the point of the OP's question is that it *could* have been implemented. – dan04 Jul 10 '14 at 00:45
  • @dan04 Yeah, but "not useful" is actually a good explanation all in itself. If not for the shortcut of not actually returning anything, there would be no need for `void` at all. It's simply a syntactic construct to allow specifying procedures (no return value), as well as functions (a single return value). Of course you could make a function that always returns `null` of some `unit` type. But what would be the point? It's not `null`, it's "nothing". What would be the point of having language features that increase complexity for *everyone* yet offer no functionality whatsoever? – Luaan Jul 10 '14 at 07:51
  • Actually, `return MethodA();` is valid C++. – fredoverflow Jul 10 '14 at 08:41
  • @dan04 - If you show me "an expression of type void", I'll show you "null". It makes no sense to assign void. You can only assign values. Void is not a value. – codenheim Jul 10 '14 at 13:08
2

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.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
  • 1
    "they did this, then they would have to manually disallow expressions of no type wherever an actual type is required" - not really no. You can treat `unit` as a normal type that's a singleton. For `MyMethod(1, 2, SomethingVoid())` the compiler already has to check whether `1` (an int) is a valid type for the first parameter, etc. As a matter of fact it could be easier the other way around, because right now you probably really have an additional code path for `void` or needing a more complicated general algorithm to handle it as well. – Voo Jul 10 '14 at 22:59
2

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
Ian
  • 33,605
  • 26
  • 118
  • 198
  • 1
    If you take the title literally, that is what it asks for. But from the code in the question, it's clear this isn't what the OP actually meant. – svick Jul 10 '14 at 17:42
  • @svick in which case the question title probably needs improving. My answer does address the question in the title and hopefully helps anyone who legitimately has that issue so not sure it deserves a down vote. I have mentioned that the other answers provide better information for the question detail, this just adds to that. – Ian Jul 10 '14 at 19:42
1

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

dee-see
  • 23,668
  • 5
  • 58
  • 91
bumbumpaw
  • 2,522
  • 1
  • 24
  • 54
-1

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
    }
}
b1ub
  • 90
  • 8
  • 1
    In his examples `return VoidMethod();` stops the execution while replacing with a simple method call does not. – dee-see Jul 10 '14 at 17:41
  • Isn´t the execution stopped anyway, because its the last line in that method? – b1ub Jul 15 '14 at 17:00