11

If I have a class like this: -

static class Foo {
   public static void Bar<T>(T item) { Console.WriteLine(item.ToString(); }
}

I know that in this example it's unnecessary to use T since all Types have ToString() on them etc. - it's simply a contrived example. What I'm more interested in is what happens under the bonnet in terms of the following: -

Foo.Bar("Hello");
Foo.Bar(123);
Foo.Bar(new Employee("Isaac"));

I broadly (think!) I understand reification i.e. if you make different types of a generic class e.g.

List<Int32>
List<String>
List<Employee>

etc. then at compile-time (or runtime?) we end up with three actual concrete types, one for each generic argument specified. Does the same apply to method calls in my first example i.e. would we still have a single class Foo but three reified Bar methods, one for String, Int32 and Employee?

Dante May Code
  • 11,177
  • 9
  • 49
  • 81
Isaac Abraham
  • 3,422
  • 2
  • 23
  • 26
  • "etc. then at compile-time (or runtime?) we end up with three actual concrete types, one for each generic argument specified." at runtime, it is one of biggest difference between C++ templates and generics. – Hamlet Hakobyan Dec 11 '12 at 16:44
  • Yes - sorry, I know that (i.e. reification as opposed to type erasure) - I was referring to whether at compile time we know whether we need all three types and are therefore generated by the runtime immediately by the CLR or whether they are generated "as required" by the CLR in a lazy fashion. – Isaac Abraham Dec 11 '12 at 16:47
  • If it was at compile time how would a generic method in a library know what it would be called with by a program? – George Duckett Dec 11 '12 at 16:51
  • Related: [clr-how-virtual-generic-method-call-is-implemented](http://stackoverflow.com/questions/6573557/clr-how-virtual-generic-method-call-is-implemented) Also, http://blogs.msdn.com/b/joelpob/archive/2004/11/17/259224.aspx (from that question's answer) – George Duckett Dec 11 '12 at 16:52
  • OK - that makes sense! The main question was though, do we get three instances of the method on a single class or something else? – Isaac Abraham Dec 11 '12 at 16:52
  • 2
    @IsaacAbraham at what level? C#: clearly no. IL: no, just one; JIT/AOT/machine-code: *possibly*, depending on the combinations (all reference-type implementations can share the same bytecode; value-type implementations cannot share)# – Marc Gravell Dec 11 '12 at 16:57
  • You say that in your example it's unnecessary to use `T`. But there is one good reason: You don't get **boxing** if `T` is a value type. That's nice. So there is a reason to use a `T` type parameter (instead of just `object`) even when there are no `where T : something` constraints. – Jeppe Stig Nielsen Dec 19 '12 at 20:31

1 Answers1

3

This is where the difference between C++ templates and C# generics comes into play.

In C++, templates cause a new method to be generated for each type it is used with. In C#, however, the code in the method is only created once. The same code runs whether you call it with an int, string, or object type parameter.

Because C# generics remain generic when compiled, they can be exposed in compiled libraries without need for re-compilation. In C++, you are required to include the original template in your consuming code, so a new copy can be compiled.

Simply put, you only get one compiled method per generic method.

Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • 2
    "Compiled" gets tricky, though; at the IL level that is correct; at the JIT level, there can be multiple "compiled" implementations - so it depends on the exact meaning of "compiled". AOT compilers will typically generate "n" methods immediately, for "n" different usages. – Marc Gravell Dec 11 '12 at 16:56
  • 2
    OK - I'm more interested in terms of a runtime perspective - sounds like you get one instance at runtime for the reference type version and a instance for every different value type, more or less? – Isaac Abraham Dec 11 '12 at 17:06