Constant expressions

  • Thread starter Thread starter Jon Shemitz
  • Start date Start date
J

Jon Shemitz

How come

const string S = "string"; // valid

is valid but

const Type T = typeof(string); // invalid

is not? "C# Language Specification" chapter 7.15 defines a constant
expression as being of the string / char / numeric types that are
aliased to System.X types, but 7.15 certainly doesn't *explain* the
type restriction.

Why is System.String a valid type for a constant expression, but
System.Type is not? Putting either on the stack involves runtime calls
.....
 
Jon Shemitz said:
How come

const string S = "string"; // valid

is valid but

const Type T = typeof(string); // invalid

is not? "C# Language Specification" chapter 7.15 defines a constant
expression as being of the string / char / numeric types that are
aliased to System.X types, but 7.15 certainly doesn't *explain* the
type restriction.

Why is System.String a valid type for a constant expression, but
System.Type is not? Putting either on the stack involves runtime calls

On the stack yes, but in the assembly no. "string" is inserted directly into
the assembly, but typeof(string) must be evaluated at run time, since
there's no way of telling whether it'll be the .NET 1.0 string, or 1.1
string. Therefore it's not constant.
 
Sean said:
On the stack yes, but in the assembly no. "string" is inserted directly into
the assembly, but typeof(string) must be evaluated at run time, since
there's no way of telling whether it'll be the .NET 1.0 string, or 1.1
string. Therefore it's not constant.

I'm not sure I understand. The ldstr gets jitted to code that
retrieves an interned value; the ldtoken / call Type.GetTypeFromHandle
gets jitted to code that retrieves a run-time generated value. You
know a string literal is of type String, but you don't know the
(reference) value at compile time; You know a typeof() expression is
of type Type, but you don't know the (reference) value at compile
time.

It appears to me like there's some sort of Limits To Special Cases
principle involved, here - System.String is the only reference type
that can be used in a constant expression - but I'm not sure.
 
Jon Shemitz said:
I'm not sure I understand. The ldstr gets jitted to code that
retrieves an interned value; the ldtoken / call Type.GetTypeFromHandle
gets jitted to code that retrieves a run-time generated value. You
know a string literal is of type String, but you don't know the
(reference) value at compile time; You know a typeof() expression is
of type Type, but you don't know the (reference) value at compile
time.

It appears to me like there's some sort of Limits To Special Cases
principle involved, here - System.String is the only reference type
that can be used in a constant expression - but I'm not sure.

You might be right on the Limit to Special Cases. As for the ldtoken, it's
not constant. If you have policy set to load version 2 of a class whenever
version 1 is requested, then the AFAIK ldtoken will result in version 2
being returned, which is not the one you compiled against.
 
constants are baked into the assembly as hardcoded values. therefore they
have to be resolved at compile time. a string literal can be solved at
compile time (not JIT compiler, but the C# compiler), but a Type cannot.
 
Back
Top