What is a CLR reference and how does it store type information?

My brain had a segfault today, trying to figure out how and when C # could work out an object type from a reference to that object. Consider the following highly non-original code example:

class Foo { public virtual void Baz() { } } class Bar : Foo { } class Program { static void Main() { Foo f = new Bar(); f.Baz(); } } 

The type of the link is Foo, but in fact the instantiated object is a panel. This Bar instance has some overhead, that is, the synchronization block index, and a reference to the MethodTable method, presumably the Bar MethodTable. If you look at the Bar object on the heap, the only key to its type is the MethodTable reference, which assumes it is a Bar.

To the question then. Is there a way for C # to find out from the actual graph of objects that f is Foo, and if so, how? Does the 'f' link have type information itself? When I call f.Baz (), do I correctly think that sending occurs through the Bar MethodTable? Is this just the case when the C # compiler uses flow analysis to figure out what is happening and prevent any illegal operations? Does the CLR really not care about declaring type Foo by the time it is translated to IL?

Sorry if this is a question with a long and poorly worded phrase - let me know if any clarification is needed!

TL DR - How does a polymorphic link work in the CLR? How is there any discrepancy between the actual vs the declared class type and could you say what was originally made from the resulting IL?

+4
source share
2 answers

You get too complicated.

Is the 'f' reference the type information itself?

No. It's not obligatory. This is simply the address at the beginning of the memory of the Bar objects that was built earlier. This object contains a virtual method table (and, possibly, a link to the Type 1 object associated with it, but it does not matter here).

When I call f.Baz (), do I correctly think that sending occurs through the Bar MethodTable?

Yes.

Is this just the case when the C # compiler uses flow analysis to figure out what is happening and prevent any illegal operations?

Flow analysis is complicated and completely unnecessary here. The compiler allows exactly those operations that are allowed for the declaration type f - which is equal to Foo . The compiler does not care at all about the actual (= dynamic) type f .

Could you tell us what was from the original declaration from the resulting IL?

It depends. An object does not have a static type, so "specifying its static type at run time" does not make sense. On the other hand, declarations vary. If the variable is a formal parameter of the method, then you can (at run time) use reflection to determine the type of declaration of the method parameter.

For local variables, this operation is again meaningless. On the other hand, IL stores this information (as metadata?) Through .locals , so theoretically there could theoretically be an inverse algorithm (Cecil and Reflector) to get a static type of variables.


1 I suppose this is actually incredible. If each object contained its own reference to the associated Type object, this would mean additional pointer overhead. In addition, this link is completely unnecessary, because the object can simply call GetType for itself to get its type. GetType needs to be executed only once for each class (for example, a static method) and is sent through a regular table of virtual functions. Thus, for each class only one reference to Type is required, unlike each object.

+5
source

Is there any way for C # to find out from the actual object graph that 'f' is Foo

This is statically known to the compiler.

Is the 'f' reference the type information itself?

Interestingly, it must be contained in IL somehow.

When I call f.Baz (), do I correctly assume that dispatch occurs through the Bar MethodTable?

Yes. And this is found through the instance f points to.

+1
source

All Articles