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
    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