13
class MyClass
{
    public void MyMethod(Type targetType = typeof(MyClass))
    {
    }
}

Isn't typeof(MyClass) a compile-time constant?

cazavientos
  • 141
  • 5

5 Answers5

11

I am not a IL expert, but seems that it calls a method at L_0005:

return typeof(int);

It´s the same of:

.maxstack 1
.locals init (
    [0] class [mscorlib]System.Type typeofvar)
L_0000: ldtoken int32
L_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
L_000a: stloc.0 
L_000b: ldloc.0 
L_000c: ret 

You can see that it isn´t a constant writing type of code:

const Type constType = typeof(int);

That returns a error:

Constant initialize must be compile-time constant
Felipe Pessoto
  • 6,855
  • 10
  • 42
  • 73
5

From MSDN - Named and Optional Parameters:

A default value must be one of the following types of expressions:

  • a constant expression;

  • an expression of the form new ValType(), where ValType is a value type, such as an enum or a struct;

  • an expression of the form default(ValType), where ValType is a value type.


typeof does not necessarily return a compile time constant as it may return different results depending on context.

Community
  • 1
  • 1
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • 1
    The type passed to `typeof` must be resolved at compile time. Hence I cannot see what you mean. If what you say is true, attributes should also disallow 'type constants'. – leppie Jan 20 '12 at 09:53
  • leppie, what you mean by "attributes should also disallow 'type constants'"? Where does attributes restrict values to be constants? – Felipe Pessoto Jan 20 '12 at 10:04
  • 1
    @Fujiy - Parameters passed in to attribute constructors need to be compile time constants. – Oded Jan 20 '12 at 10:06
  • 2
    Oded, the rule is: A Constant or typeof expression or a array creation – Felipe Pessoto Jan 20 '12 at 10:11
4

because it isn't necessarily a constant expression. your example features a typeof on a simple class but what if the class was generic? obviously this isn't constant by far:

class MyClass<T>
{
  public void MyMethod(Type targetType = typeof(MyClass<T>))
  {
  }
} 
mtijn
  • 3,610
  • 2
  • 33
  • 55
  • 1
    You might still expect it to be constant if you're used to generic types being done the way they are in C++, where each possible type `T` generates a new instance of the class. That's not how it works in C# and .NET, so in C# `typeof(T)` can't be a compile-time constant, but in a template-based generic language it would be. – Ed Avis Oct 15 '19 at 16:29
3

This is old but if someone is looking for a Workaround:

    class MyClass
    {
        public void MyMethod(Type targetType = null)
        {
            if(targetType == null)
            {
                targetType = typeof(MyClass);
            }
        }
    }

gbelzile
  • 84
  • 2
1

Isn't typeof(MyClass) a compile-time constant?

That particular expression is statically resolvable, yes, but typeof() is evaluated at execution time (because of generics), so the rule must be that a typeof() call isn't a compile-time constant.

I do wonder whether it was in C# 1.0, when there was no such argument to be made...

AakashM
  • 62,551
  • 17
  • 151
  • 186
  • 1
    I don't think generics is the only reason for this. I think it's because this works: `typeof(ClassInExternalAssembly)`. It cannot be resolved until the actual external assembly is loaded, and therefore, it's not constant. – Aidiakapi Oct 27 '12 at 12:10