Casting boxed value types in C#

I came across these two posts on Eric Lip­pert’s blog yes­ter­day which I found very inter­est­ing:

Rep­re­sen­ta­tion and Iden­ti­ty

Cast oper­a­tors do not obey the dis­trib­u­tive law

The blog posts go into a lot of details but long sto­ry short, if you box a val­ue type you can’t unbox it to anoth­er type:

image

It would result in an Invalid­Cas­tEx­cep­tion, and the big ques­tion is, if there exists a con­ver­sion from int to long why can’t the run­time work it out?

Well, con­sid­er three sim­ple types A, B and C, where B inher­its from A and C pro­vides an explic­it con­vert­er from A:

public class A {}
public class B : A {}
public class C 
{
    public static explicit operator C(A a)
    {
        return new C();
    }
}

There exists two types of con­ver­sion which you can achieve using the Cast­ing oper­a­tor:

var b = new B();
var a = ( A ) b; // inheritance-based conversion, equivalent to var a = b as A;
var c = ( C ) a; // operator-based conversion

In essence, the inher­i­tance-based con­ver­sion is just show­ing the same object in a ‘new light’, where­as the oper­a­tor-based con­ver­sion requires a spe­cial treat­ment on a case-by-case basis in the form of con­ver­sion meth­ods.

Inher­i­tance-based Con­ver­sion

(rep­re­sen­ta­tion-pre­serv­ing)

Oper­a­tor-based Con­ver­sion

(rep­re­sen­ta­tion-chang­ing)

New object is not con­struct­ed con­struct­ed
New vari­able points to orig­i­nal object new object
Chang­ing the new vari­able changes the orig­i­nal object doesn’t change the orig­i­nal object
Con­ver­sion is fast slow

A box val­ue type is an object, so as far as the com­pil­er is con­cerned it could be any­thing. There­fore by allow­ing a boxed val­ue type to be cast to a dif­fer­ent type you intro­duce new chal­lenges to the com­pil­er:

  1. it needs to gen­er­ate more code at run­time (from CIL to machine code by the JIT-Com­pil­er) because the com­pil­er needs to check if it needs to call a con­ver­sion method after unbox­ing the boxed val­ue type.
  2. it also needs to work out which con­ver­sion method to call, this requires sig­nif­i­cant amount of analy­sis giv­ing that there can be an arbi­trary num­ber of con­ver­sion meth­ods (both built-in and user-defined) on arbi­trar­i­ly many types.

Unfor­tu­nate­ly the cost of meet­ing these chal­lenges is per­for­mance, and the sen­si­ble default was to be “fast and pre­cise” but still allow­ing this type of con­ver­sion through the Con­vert class.

Parting thoughts…

Towards the end of the post there was a warn­ing to those look­ing to abuse the new dynam­ic type sup­port in C# 4 ;-)

…if the argu­ment to the cast is of type “dynam­ic” instead of object. The com­pil­er actu­al­ly gen­er­ates code which starts a mini ver­sion of the com­pil­er up again at run­time, does all that analy­sis, and spits fresh code. This is NOT FAST, but it is accu­rate, if that’s what you real­ly need. (And the spit code is then cached so that the next time this call site is hit, it is much faster.)…”