c# - What is the Implementation of Generics for the NET Common Language Runtime -
when use generic collections in c# (or .net in general), compiler leg-work developers used have of making generic collection specific type. . . . saves work?
now think it, can't right. because without generics, used have make collections used non-generic array internally, , there boxing , unboxing (if collection of value types), etc.
so, how generics rendered in cil? doing impliment when want generic collection of something? don't want cil code examples (though ok), want know concepts of how compiler takes our generic collections , renders them.
thanks!
p.s. know use ildasm @ cil still looks chinese me, , not ready tackle that. want concepts of how c# (and other languages guess too) render in cil handle generics.
forgive verbose post, topic quite broad. i'm going attempt describe c# compiler emits , how that's interpreted jit compiler @ runtime.
ecma-335 (it's written design document; check out) it's @ knowing how everything, , mean everything, represented in .net assembly. there few related cli metadata tables generic information in assembly:
- genericparam - stores information generic parameter (index, flags, name, owning type/method).
- genericparamconstraint - stores information generic parameter constraint (owning generic parameter, constraint type).
- methodspec - stores instantiated generic method signatures (e.g. bar.method<int> bar.method<t>).
- typespec - stores instantiated generic type signatures (.e.g. bar<int> bar<t>).
so in mind, let's walk through simple example using class:
class foo<t> { public t someproperty { get; set; } }
when c# compiler compiles example, define foo in typedef metadata table, other type. unlike non-generic type, have entry in genericparam table describe generic parameter (index = 0, flags = ?, name = (index string heap, "t"), owner = type "foo").
one of columns of data in typedef table starting index methoddef table continuous list of methods defined on type. foo, we've defined 3 methods: getter , setter someproperty , default constructor supplied compiler. result, methoddef table hold row each of these methods. 1 of important columns in methoddef table "signature" column. column stores reference blob of bytes describes exact signature of method. ecma-335 goes great detail these metadata signature blobs, won't regurgitate information here.
the method signature blob contains type information parameters return value. in our example, setter takes t , getter returns t. well, t then? in signature blob, it's going special value means "the generic type parameter @ index 0". means row in genericparams table has index=0 owner=type "foo", our "t".
the same thing goes auto-property backing store field. foo's entry in typedef table have starting index field table , field table has "signature" column. field's signature denote field's type "the generic type parameter @ index 0".
this , good, code generation come play when t different types? it's responsibility of jit compiler generate code generic instantiations , not c# compiler.
let's take @ example:
foo<int> f1 = new foo<int>(); f1.someproperty = 10; foo<string> f2 = new foo<string>(); f2.someproperty = "hello";
this compile cil:
newobj <memberreftoken1> // new foo<int>() stloc.0 // store in local "f1" ldloc.0 // load local "f1" ldc.i4.s 10 // load constant 32-bit integer value 10 callvirt <memberreftoken2> // call f1.set_someproperty(10) newobj <memberreftoken3> // new foo<string>() stloc.1 // store in local "f2" ldloc.1 // load local "f2" ldstr <stringtoken> // load "hello" (which in user string heap) callvirt <memberreftoken4> // call f2.set_someproperty("hello")
so what's memberreftoken business? memberreftoken metadata token (tokens 4 byte values most-significant-byte being metadata table identifier , remaining 3 bytes row number, 1-based) references row in memberref metadata table. table stores reference method or field. before generics, table store information methods/fields you're using types defined in referenced assemblies. however, can used reference member on generic instantiation. let's memberreftoken1 refers first row in memberref table. might contain data: class = typespectoken1, name = ".ctor", blob = <reference expected signature blob of .ctor>.
typespectoken1 refer first row in typespec table. above know table stores instantiations of generic types. in case, row contain reference signature blob "foo<int>". memberreftoken1 saying referencing "foo<int>.ctor()".
memberreftoken1 , memberreftoken2 share same class value, i.e. typespectoken1. differ, however, on name , signature blob (methodreftoken2 "set_someproperty"). likewise, memberreftoken3 , memberreftoken4 share typespectoken2, instantiation of "foo<string>", differ on name , blob in same way.
when jit compiler compiles above cil, notices it's seeing generic instantiation hasn't seen before (i.e. foo<int> or foo<string>). happens next covered pretty shiv kumar's answer, won't repeat in detail here. put, when jit compiler encounters new instantiated generic type, may emit whole new type type system field layout using actual types in instantiation in place of generic parameters. have own method tables , jit compilation of each method involve replacing references generic parameters actual types instantiation. it's responsibility of jit compiler enforce correctness , verifiability of cil.
so sum up: c# compiler emits metadata describing what's generic , how generic types/methods instantiated. jit compiler uses information emit new types (assuming isn't compatible existing instantiation) @ runtime instantiated generic types , each type have own copy of code has been jit compiled based on actual types used in instantiation.
hopefully made sense in small way.
Comments
Post a Comment