Which value types can be compared with Opcodes.ceq? RRS feed

  • Question

  • I'm doing some IL code generation and realizing that some value types (e.g., integer) can be compared using Ceq but others (e.g., decimal) require a call to op_Equality.  An attempt to Ceq on decimal types is detected as invalid IL by PeVerify. 

    What's the rule on this?  Is it that "if op_equality is defined on the type, use it, else you can Ceq?" (for value types, of course.)





    Leo Tohill
    Friday, November 12, 2010 6:30 PM

All replies

  • Hi Leo,

    CLR treats int and decimal differently.


    Following C# code:


            static void Main(string[] args)


                int a = 10;

                int b = 20;


                bool result = a == b;


                decimal da = 10;

                decimal db = 11;


                result = da == db;



    Will be compiled into IL instructions:


    .method private hidebysig static void  Main(string[] args) cil managed



      // Code size       39 (0x27)

      .maxstack  2

      .locals init ([0] int32 a,

               [1] int32 b,

               [2] bool result,

               [3] valuetype [mscorlib]System.Decimal da,

               [4] valuetype [mscorlib]System.Decimal db)

      IL_0000:  nop

      IL_0001:  ldc.i4.s   10

      IL_0003:  stloc.0

      IL_0004:  ldc.i4.s   20

      IL_0006:  stloc.1

      IL_0007:  ldloc.0

      IL_0008:  ldloc.1

      IL_0009:  ceq

      IL_000b:  stloc.2

      IL_000c:  ldc.i4.s   10

      IL_000e:  newobj     instance void [mscorlib]System.Decimal::.ctor(int32)

      IL_0013:  stloc.3

      IL_0014:  ldc.i4.s   11

      IL_0016:  newobj     instance void [mscorlib]System.Decimal::.ctor(int32)

      IL_001b:  stloc.s    db

      IL_001d:  ldloc.3

      IL_001e:  ldloc.s    db

      IL_0020:  call       bool [mscorlib]System.Decimal::op_Equality(valuetype [mscorlib]System.Decimal,

                                                                      valuetype [mscorlib]System.Decimal)

      IL_0025:  stloc.2

      IL_0026:  ret

    } // end of method Program::Main


    We can see that “int a = 10;” is compiled to


      IL_0001:  ldc.i4.s   10

      IL_0003:  stloc.0


    While “decimal da = 10;” is compiled to


      IL_000c:  ldc.i4.s   10

      IL_000e:  newobj     instance void [mscorlib]System.Decimal::.ctor(int32)

      IL_0013:  stloc.3


    From my understanding, CLR knows how to compare int values, but, decimal is considered as a “user-defined type”, CLR invoke its Equals method to do comparation.

    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Saturday, November 13, 2010 5:11 AM
  • Thankyou Eryang,


    you  have illustrated what I discovered. My question is, how can I determine which  way a type will be handled?  (Other than examining a  disassembly of any  type that I am interested in?)  There must be something in the CLR spec about this but I haven't found it.





    Leo Tohill
    Sunday, November 14, 2010 5:47 AM