Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
263 views
in Technique[技术] by (71.8m points)

c# - How, when and where are generic methods made concrete?

This question got me wondering about where the concrete implementaiton of a generic method actually comes into existence. I've tried the google but am not coming up with the right search.

If we take this simple example:

class Program
{
    public static T GetDefault<T>()
    {
        return default(T);
    }

    static void Main(string[] args)
    {
        int i = GetDefault<int>();
        double d = GetDefault<double>();
        string s = GetDefault<string>();
    }
}

in my head I've always assumed that at some point it results in an implementation with the 3 necessary concrete implementations such that, in naive pseudo mangling, we would have this logical concrete implementaiton where the specific types used result in the correct stack allocations etc.

class Program
{
    static void Main(string[] args)
    {
        int i = GetDefaultSystemInt32();
        double d = GetDefaultSystemFloat64();
        string s = GetDefaultSystemString();
    }

    static int GetDefaultSystemInt32()
    {
        int i = 0;
        return i;
    }
    static double GetDefaultSystemFloat64()
    {
        double d = 0.0;
        return d;
    }
    static string GetDefaultSystemString()
    {
        string s = null;
        return s;
    }
}

Looking at the IL for the generic program it is still expressed in terms of generic types:

.method public hidebysig static !!T  GetDefault<T>() cil managed
{
  // Code size       15 (0xf)
  .maxstack  1
  .locals init ([0] !!T CS$1$0000,
           [1] !!T CS$0$0001)
  IL_0000:  nop
  IL_0001:  ldloca.s   CS$0$0001
  IL_0003:  initobj    !!T
  IL_0009:  ldloc.1
  IL_000a:  stloc.0
  IL_000b:  br.s       IL_000d
  IL_000d:  ldloc.0
  IL_000e:  ret
} // end of method Program::GetDefault

So how and at what point is it decided that an int, and then a double and then a string have to be allocated on the stack and returned to the caller? Is this an operation of the JIT process? Am I looking at this in the completely wrong light?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In C#, the concepts of generic types and methods is supported by the runtime itself. The C# compiler does not need to actually create a concrete version of a generic method.

The actual "concrete" generic method is created at runtime by the JIT, and does not exist in the IL. The first time a generic method is used with a type, the JIT will see if it's been created, and if not, construct the appropriate method for that generic type.

This is one of the fundamental differences between generics and things like templates in C++. It's also the main reason for many of the limitations with generics - since the compiler isn't actually creating the runtime implementation for types, the interface restrictions are handled by compile time constraints, which make generics a bit more limiting than templates in C++ in terms of potential use cases. However, the fact that they are supported in the runtime itself allows creation of generic types and usage from libraries possible in ways that aren't supported in C++ and other compile-time created template implementations.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...