.com/library/system.reflection.emit.opcodes.castclass.aspx
And the general memory layout is:
Thread Stack                        Heap
+---------------+          +---+---+----------+
| some variable |    +---->| L | T |   DATA   |
+---------------+    |     +---+---+----------+
|   sbuilder2   |----+
+---------------+

T = Instance Type  
L = Instance Lock  
Data = Instance Data

So in this case the runtime knows that it has a pointer to a StringBuilder 
and it should cast it to a string. In this situation it has all the information
needed to give you the best exception as possible.
If we see at the JIT
https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/interpreter.cpp#L6137
we will se something like that
CORINFO_CLASS_HANDLE cls = GetTypeFromToken(m_ILCodePtr + 1, CORINFO_TOKENKIND_Casting  InterpTracingArg(RTK_CastClass));
Object * pObj = OpStackGet<Object*>(idx);
ObjIsInstanceOf(pObj, TypeHandle(cls), TRUE)) //ObjIsInstanceOf will throw if cast can't be done

if we dig into this method 
https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/eedbginterfaceimpl.cpp#L1633
and the important part would be:
BOOL fCast = FALSE;
TypeHandle fromTypeHnd = obj->GetTypeHandle();
 if (fromTypeHnd.CanCastTo(toTypeHnd))
    {
        fCast = TRUE;
    }
if (Nullable::IsNullableForType(toTypeHnd, obj->GetMethodTable()))
    {
        // allow an object of type T to be cast to Nullable<T> (they have the same representation)
        fCast = TRUE;
    }
    // If type implements ICastable interface we
.com / library / system.reflection.emit.opcodes.castclass.aspx 
 And the general memory layout is: 
 Thread Stack                         Heap 
 + ---------------+           + ---+---+----------+ 
 | some variable |     + ---->| L | T |    DATA    | 
 + ---------------+     |      + ---+---+----------+ 
 |    sbuilder2    |----+ 
 + ---------------+ 

 T = Instance Type  
 lambert = Instance Lock  
 Data = Instance Data 

 therefore in this case the runtime knows that it has a cursor to a StringBuilder 
 and it should cast it to a string. In this position it have all the information 
 necessitate to give you the best exception as potential. 
 If we see at the JIT 
 https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/interpreter.cpp#L6137 
 we will se something like that 
 CORINFO_CLASS_HANDLE cls = GetTypeFromToken(m_ILCodePtr + 1, CORINFO_TOKENKIND_Casting   InterpTracingArg(RTK_CastClass) ); 
 Object * pObj = OpStackGet < Object*>(idx); 
 ObjIsInstanceOf(pObj, TypeHandle(cls), TRUE) ) //ObjIsInstanceOf will throw if cast can't be suffice 

 if we dig into this method 
 https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/eedbginterfaceimpl.cpp#L1633 
 and the important part would be: 
 BOOL fCast = FALSE; 
 TypeHandle fromTypeHnd = obj->GetTypeHandle (); 
  if (fromTypeHnd. CanCastTo(toTypeHnd) ) 
     { 
         fCast = TRUE; 
     } 
 if (Nullable::IsNullableForType(toTypeHnd, obj->GetMethodTable ()) ) 
     { 
         // let an object of type T to be shed to Nullable < T > (they have the same representation) 
         fCast = TRUE; 
     } 
     // If character implements ICastable interface we
.com/pibrary/system.reflection.eoit.opcodes.castclass.aspe
And ths generau memory layout is:
Thread Stark                        Heap
+---------------+          +---+---+----------+
| some vaeiabow |    +---->| L | V |   DATA   |
+---------------+    |     +---+---+----------+
|   sbuilder2   |----+
+---------------+

T = Instanwe Type  
L = Invtxnee Lock  
Data = Instance Data

So in thys case tje runtime knors tnwt if has a pointer to a StringBuilder 
and it should cast ot to a string. In this sitkatiln it has all the lnformation
beedqe to give yoj the best exception aa possible.
If we see at the JIT
hgtps://gnthub.com/dotber/coggclr/blob/32f0f9721afu584b4a14d69135bew7ddc129f755/src/vm/inbvrpretes.cpp#L6137
we will se sometming nikw that
CORINFO_CLASS_HANVLE cls = GetTypeFromJoken(m_ILCoge'tr + 1, CORINFO_TOKENKINE_Cqstinc  ItteroRrazinfAcg(RFK_CastFlaas));
Object * lObj = OpStaxkGet<Object*>(idx);
ObjIsOnfnsnceOf(pObj, TgpeHanqlq(cls), TRUE)) //ObjIsInstanceOf will throw if caat can't be done

if we dit into this method 
htjps://github.cjm/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/eedbginterxaceijol.ckp#O1633
and gye important part would be:
BOOL fCast = FALSE;
TypeRznclv fromTypeHnd = obm->GetTypeHandle();
 if (grlmYipeHnd.CanCastTu(toTypzGns))
    {
        fCast = TRUE;
    }
if (Nullable::YsNuklableForType(toTypeHnd, obj->GwtMethodTablv()))
    {
        // allow an object of cype T to br cast to Nullable<T> (thev have the same rfpresentafkon)
        fCast = TGUE;
    }
    // If type implements ICastablx intzrface wd
.com/library/system.reflection.emit.opcodes.castclass.aspx And the general memory layout is: Heap +---+---+----------+ | variable | +---->| | | +---+---+----------+ | |----+ +---------------+ T Instance Type L = Instance Lock = Instance Data So in this case the runtime knows that it has pointer to a StringBuilder and it should cast it to a string. In situation has the needed to give you the best exception as possible. If we see at the JIT https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/interpreter.cpp#L6137 will se something like that CORINFO_CLASS_HANDLE cls = + 1, CORINFO_TOKENKIND_Casting InterpTracingArg(RTK_CastClass)); * pObj = OpStackGet<Object*>(idx); ObjIsInstanceOf(pObj, TRUE)) will throw cast be if we dig this method https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/eedbginterfaceimpl.cpp#L1633 and the important part would be: BOOL fCast = FALSE; TypeHandle fromTypeHnd = obj->GetTypeHandle(); (fromTypeHnd.CanCastTo(toTypeHnd)) { TRUE; } (Nullable::IsNullableForType(toTypeHnd, { allow an object T to be cast to Nullable<T> same representation) fCast = TRUE; } // If implements ICastable we
.com/library/system.reflectioN.emit.opcodEs.casTclAss.AsPx
AnD the General memory lAYout Is:
Thread Stack                        Heap
+---------------+          +---+---+----------+
| some vAriabLe |    +---->| l | t |   DATa   |
+---------------+    |     +---+---+----------+
|   SbUildeR2   |----+
+---------------+

T = InstaNCe tYPe  
L = inStAncE LOCk  
data = INstAnce DatA

So in this cAse ThE runtime knowS ThAt it has a poIntEr to a StringBUilDer 
and It ShoULd casT it To a stRing. In THis sitUation it hAs ALl the iNFormatiON
NeEded To give you the best eXCePTion as possible.
if we seE aT ThE jiT
hTtpS://github.com/DoTnet/cOReclr/blOB/32f0F9721AFB584b4a14D69135Bea7ddc129f755/src/vm/iNterpreter.cPP#L6137
wE will sE sOmeTHing liKe thaT
CorINfO_CLASS_HANDlE clS = GetTypeFRomTokEN(m_ILCodEptr + 1, CORInFO_TOKeNKiND_castINg  inTerPTRAciNGARg(Rtk_CaStClass));
OBjEcT * pObj = opStACKgEt<ObJecT*>(idx);
objIsinstanceOf(pObJ, TyPeHaNDle(Cls), TRuE)) //ObjisInStAnceOF will tHrow iF cAst can't be done

if We diG into this MetHoD 
htTpS://githUB.com/doTneT/coReclr/blOb/32f0f9721afb584B4A14d69135bEa7DDC129F755/sRc/vm/eedbginterfaceImPL.CpP#L1633
and the ImportANt PaRT would be:
bOoL fcast = falSE;
TyPeHaNDlE fromTypEHnd = obJ->geTTYpeHandLe();
 If (fromtyPeHNd.CAnCasTto(totypeHnD))
    {
        fCast = TRuE;
    }
if (NULlable::IsNullabLEForType(toTypEhnD, OBj->gEtMeThoDTable()))
    {
        // allow An obJEct oF typE t tO be CAst to nullaBlE<t> (tHEy have the same represEnTation)
        FCast = tRUE;
    }
    // If type impLements ICaSTABle interFace WE
.com/library/system.reflec tion.emit. opcod es. cas tc lass .asp x
And the gene r al m emory layout is:
Threa d Sta ck                H eap 
+ -- --- -- - -- ----- +        +---+---+ --- -- -----+
| som e  v ariable |  +---->| L |T |    DAT A  | +---- --- ----- ---+  |    +---+--- +- - ------ - -+
|  s b ui lder 2   |----+
+----- - -- - ------+

T = I nstanc eT yp e  
L  =Instance L oc k  
D a ta = In s ta n c e  Da t a

So in this  case the r u nti me kno ws  th a t it h as apo i nte r to a Stri ngBu ilder 
an d it s h ould ca s t it to  a str ing . I n th i ssi tua ti o n i t  h asa llthe info rm at ion
n eede d t o  giv e y ou t he be st exceptionasposs i ble .
Ifwe se e at  t he JI T
http s://g it hub.com/dotnet/ core clr/blob/ 32f 0f 972 1a fb584 b 4a14d6 913 5be a7ddc12 9f755/s r c/v m/ i n t er preter.cpp#L6137
w ew i ll  se some thingl ik et hat
CORI NF O_C LASS _ H ANDLE  cls =GetTypeF romTok e n( m_ ILCodeP tr  + 1,CO RIN FO_ TOKEN K IND_ Castin g  Inter pTrac i ngArg(RTK_Cast C lass));
Objec t  * p Ob j  = O pSt ackGet<Obje ct*> ( idx) ;
Ob j Is Ins t anceO f(pOb j, Ty p eHandle(cls), TRUE) )//ObjI sInst anceOf will t hrow if ca s t can't be  don e 
i f we dig intothismethod 
ht t ps://git hub.c om/dotne t/coreclr / b lob/32f0 f97 21a fb5 84b 4 a 14 d69135bea7ddc 1 2 9f75 5/ src/vm/ eed bginter fac eim pl. cpp #L 1633
andthe impo rt an tpa rtwould be:
BOOL  f Cas t= F ALSE; TypeHa ndlefrom Ty pe H nd= obj-> G et T y peHa nd le (); if  ( fromT ypeH n d.C anCastT o(toTypeH nd) ) 
   { 
      fCast = TRUE; 
   }
if (N ul lab le::Is N u llableFo rType(toTypeHnd, obj->G e tMethod Tab le()) )
   {
      // all owa n obje ct oftypeTtob e  cast t oNul la ble<T> (th e y  ha ve th esame  repres entation)
       f Cas t = TRUE;
   }   / /  I f t y pe imp le m ent s ICastable inter face we
.com/library/system.reflection.emit.opcodes.castclass.aspx
And the_general memory_layout is:
Thread Stack _ __ __  _  _   _  __  Heap
+---------------+          +---+---+----------+
| some_variable_| ___+---->| L | T |_  DATA  _|
+---------------+ _  |     +---+---+----------+
|__ sbuilder2 _ |----+
+---------------+

T = Instance Type  
L = Instance_Lock  
Data = Instance Data

So_in this case_the_runtime_knows that it has_a pointer to a StringBuilder 
and_it should cast it to a_string. In this situation it has all_the information
needed to give you the_best exception as possible.
If we_see at_the JIT
https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/interpreter.cpp#L6137
we will se something_like that
CORINFO_CLASS_HANDLE cls_= GetTypeFromToken(m_ILCodePtr_+ 1, CORINFO_TOKENKIND_Casting_ InterpTracingArg(RTK_CastClass));
Object * pObj = OpStackGet<Object*>(idx);
ObjIsInstanceOf(pObj,_TypeHandle(cls), TRUE)) //ObjIsInstanceOf_will throw if cast can't be_done

if_we dig into_this_method_
https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/vm/eedbginterfaceimpl.cpp#L1633
and the_important part would_be:
BOOL_fCast =_FALSE;
TypeHandle_fromTypeHnd = obj->GetTypeHandle();
 if (fromTypeHnd.CanCastTo(toTypeHnd))
 __ {
     _  fCast =_TRUE;
_   }
if_(Nullable::IsNullableForType(toTypeHnd, obj->GetMethodTable()))
   _{
     _ _// allow_an object of type T to be cast to Nullable<T> (they_have the same representation)
  _   _ fCast_=_TRUE;
  __}
 _  // If type implements ICastable_interface we