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.