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?
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 Action
s:
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With