23

Quoting MSDN - const (C# reference):

A constant expression is an expression that can be fully evaluated at compile time. Therefore, the only possible values for constants of reference types are string and a null reference.

According to: typeof(T) vs. Object.GetType() performance, typeof(T) is a compile time expression.

So why can't a Type be a constant value?

The following code will not compile:

public const Type INT_TYPE = typeof(int);
Community
  • 1
  • 1
Matias Cicero
  • 25,439
  • 13
  • 82
  • 154

5 Answers5

12

Constants are substituted by the compiler with literal values in the resulting IL code. But typeof is a method call:

typeof(int);

// Becomes:
L_0000: ldtoken int32
L_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
Kapol
  • 6,383
  • 3
  • 21
  • 46
10

The C# compiler and IL certainly support types as constant expressions, at least in certain situations. Look at attributes, they use this a lot:

[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]

The type is embedded as a string in the compiler generated code, above line compiles to the following IL code:

.custom instance void System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class System.Type) = (
    01 00 39 53 79 73 74 65 6d 2e 43 6f 6c 6c 65 63
    74 69 6f 6e 73 2e 47 65 6e 65 72 69 63 2e 4d 73
    63 6f 72 6c 69 62 5f 43 6f 6c 6c 65 63 74 69 6f
    6e 44 65 62 75 67 56 69 65 77 60 31 00 00
)

If you inspect the binary data, you will notice this is the fully qualified class name without any assembly identification (System.Collections.Generic.Mscorlib_CollectionDebugView`1).

To answer your question: I do not see any technical reason why this should not be possible, nor can I imagine compatibility considerations that prevent it as there is no assembly reference serialized and therefore the DLL declaring this type still can be updated without affecting the previously compiled type referencing it.

Christoph
  • 3,322
  • 2
  • 19
  • 28
2

From MSDN:

Constants can be numbers, Boolean values, strings, or a null reference.

Constants are basically limited to primitive values that can be represented as a binary value at compile-type (since it is "injected" into the client code when it is compiled). Since Type is a class that has several properties, there's not a simple binary representation that can be "baked into" the client code.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
0

Type is a run-time reference to a TypeInfo object. It is not known until run-time where that TypeInfo object will reside.

jwdonahue
  • 6,199
  • 2
  • 21
  • 43
-1
public const Type INT_TYPE = typeof(int);

The reason the above code will not compile is the exact reason stated by MSDN- the value of the constant cannot be determined at the time the application is compiled. Using typeof(int) requires determining the value for the constant at runtime. In theory, .NET could allow the statement above to compile, but then it would not be a constant in a strict sense of the word.

Joshua Dannemann
  • 2,003
  • 1
  • 14
  • 34
  • 1
    Why isn't `typeof(int)` known at compile time? – NetMage May 04 '18 at 21:06
  • 2
    Because you can compile code for `AnyCPU` and `typeof(int)` would be different on various architectures. `Type` is a run-time **_reference_** to a type, not a compile time constant. – jwdonahue Oct 19 '18 at 04:14
  • @jwdonahue, not true. https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/exx3b86w(v=vs.90) . Only pointer and reference type sizes change, and presumably that's determined by which framework is running (32-bit or 64-bit). – Matt Chambers Jul 15 '20 at 14:29
  • @MattChambers `typeof(int) != sizeof(int)`. The actual value of `Type` returned by `typeof(int)` can vary across systems. I can think of no reason why it might not change from one run-time to another on the same box. `Type` for a particular instance of a type is derived at run-time, not compile time. – jwdonahue Jul 15 '20 at 16:33
  • 1
    Well, if the sizes aren't different, why would the typeof result need to be different? I.e. why not constant? – Matt Chambers Jul 16 '20 at 17:15