Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What was the design rationale for making void not a primitive type?

When using reflection Type.IsPrimitive on a void type returns false.Coming from a C++ background this was surprising.

Looking at the C# 6.0 spec (Page 82) does not mention the void type, which could mean that it isn't categorized as a type altogether.

Is there anything in the language spec or otherwise that categorizes void as something else. Or any other discussion or such which mentions the reason behind this?

like image 465
crezefire Avatar asked Mar 17 '17 09:03

crezefire


3 Answers

Why isn't void a primitive type? Because it isn't something you can instantiate. It isn't a primitive type, nor a reference type. It is nothing at all.

Eric Lippert describes some 'problems' with the void type in this post on Software Engineering, which goes into the specifics of void as a type to use in delegates and Actions:

A type system is essentially a system for making logical deductions about what operations are valid on particular values; a void returning method doesn't return a value, so the question "what operations are valid on this thing?" don't make any sense at all. There's no "thing" for there to be an operation on, valid or invalid.

Making it a primitive type defeats the special meaning and purpose of void in the VES (Virtual Execution System), as Eric explains later on:

The effect of a call to a void method is fundamentally different than the effect of a call to a non-void method; a non-void method always puts something on the stack, which might need to be popped off. A void method never puts something on the stack.

Making void a primitive type breaks this rule, although you could argue its usefulness, as Eric explains further in the post referenced.

like image 131
Patrick Hofman Avatar answered Nov 20 '22 12:11

Patrick Hofman


void is not a type, it is a keyword. Just like it is in C++, means the exact same thing. Keywords play an exalted role in a language, they can only appear in certain places and the parser is allowed to make hard assumptions about the programmer's intention.

Primarily role is to generate good error messages. Obvious on a statement like return 42; in a method declared void, you get a crystal-clear "hey, you said it won't return anything" error message. Less obvious is that they are very useful to recover from basic syntax errors, a missing } closing brace for example is a pretty hard error to recover from. When the parser encounters void while parsing a method body then it can reset the parser state and start generating good error messages again.

That the System.Void type exists at all is a quirk related to metadata. The rough equivalent to a .h file in C++. They exist primary to deal with technical restrictions in C++, it has no concept of modules, it uses a single-pass compilation model and demands that declarations always appear before definitions. Pretty painful busywork in C++, albeit that editor tooling can help a bit. No such restrictions in C#, the compiler generates the declaration from the definition.

Metadata describes a method in detail, stored in a MethodDef and MethodDefSig records in the metadata. Two basic ways the CLR designers could have expressed the notion of "this method does not return data". An obvious way is that they could have used a bit in the MethodAttributes enum, something like "HasNoReturnValue". But since lots of methods do have a non-void return type, and space for it is reserved in the MethodDefSig record anyway, they just picked a sentinel value as the return type. System.Void.

Reflecting on the System.Void type is not generally useful. Realistically they could have picked any value for IsPrimitive and it wouldn't have made any difference. False was a logical choice, it does not describe a type.

like image 30
Hans Passant Avatar answered Nov 20 '22 11:11

Hans Passant


From reading the C# Specification, there is no mention of a type void. It is written about as a return type. In the table of contents, it is not categorised under reference or value types. It is mentioned as a keyword.

The section on the typeof function says:

The third form of typeof-expression consists of a typeof keyword followed by a parenthesized void keyword. The result of an expression of this form is the System.Type object that represents the absence of a type. The type object returned by typeof(void) is distinct from the type object returned for any type. This special type object is useful in class libraries that allow reflection onto methods in the language, where those methods wish to have a way to represent the return type of any method, including void methods, with an instance of System.Type.

Which to me indicates that void has an associated type but is only used in the case where you want reflection to give you something tangible because of the type system. Otherwise void is just a keyword.

like image 8
Callum Linington Avatar answered Nov 20 '22 13:11

Callum Linington