1

Will typeof(T) == typeof(string) where T is a generic type argument, be compiled into a constant Boolean value, since the condition is knowable at compile time?

Triynko
  • 18,766
  • 21
  • 107
  • 173
  • 1
    No, it won't. Why it should compile into constant? Generic types in .NET are being constructed at run-time. – Dennis Dec 16 '15 at 07:21
  • Not so much that it should, as it could, since it would be resolvable at compile time if it was compiled like c++ templates. In that case, it certainly should compile into a constant as an optimization, but not in C# since the types retain their generic type parameters at runtime. I've done quite a bit of work with reflection and construction of generic types at runtime, but someone tried to tell me they were the same as c++ templates compiled into a separate type for each generic type used and I doubted what a knew for a minute. Just clearing things up. – Triynko Dec 17 '15 at 12:41

2 Answers2

5

Generic type data exists in the IL - it is not erased like in Java. So: no, the C# compiler doesn't compile this to a constant; it compiles it the IL that talks about a generic type parameter.

The JIT on this is then reused for all reference type permutations (only each value-type permutation requires a separate JIT, for size/boxing/etc reasons). Since string is a reference-type, this means that Foo<string> (where typeof(T)==typeof(string) is true) uses the same JIT output as Foo<SomeClass> (where typeof(T)==typeof(string) is false). So no: this is explicitly not a constant, even at JIT time.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • So would this also apply the same way to a primitive type like `typeof(T) == typeof(int)`? Or would the JIT be able to optimize that to a constant? – Triynko Dec 17 '15 at 12:52
  • @Triynko that's an interesting question, and it would depend on the JIT. In theory yes: that *is* well known, because it will JIT for all value-type T, so the `typeof(T)` in the `int` case will be reducible. Whether it **does** do that, however, would require looking at the generated machine code. I do not know, basically. – Marc Gravell Dec 17 '15 at 14:15
1

I've done some performance tests on this with the following results:

  1. If the generic Type is a class (not a struct), there is no compiler nor runtime optimization on the statement: if (typeof(T) == typeof(someClass)).
  2. If the generic Type is a struct, there is compiler or runtime optimization on the if-statements of the format: if (typeof(T) == typeof(someStruct)), up to a certain point (the size of the method seems to matter: in my test-rig after 998 if-statements). After this point, performance degrades drastically: whereas these is no performance penalty for adding extra if-statements of this type before this point, an extra if-statement after this point causes a performance degradation of over 10000 %.
  3. Limiting the generic Type to a certain class or limit it to a struct does not change performance.
  4. It is the size of the method that matters, not the size of the class. Thus 10 methods may perform better than 1 large method doing the same actions.

Tested with C# on VS2017 and .net 4.6.2, with optimization turned on.

Wolfgang Grinfeld
  • 870
  • 10
  • 11