一、高级语言的比较运算
比较运算,在C#中很简单,一般直接用如下运算符即可:
等于 | == |
不等于 | != |
小于 | < |
小于等于 | <= |
大于 | > |
大于等于 | >= |
二、MSIL 中基元类型的比较运算
在动态方法中,使用 ILGenerator 对象,OpCodes 与上述比较运算相关的,则有许多:
Beq | 如果两个值相等,则将控制转移到目标指令 |
Bgq | 如果第一个值大于或等于第二个值,则将控制转移到目标指令。 |
Bge_Un | 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令。 |
Bgt | 如果第一个值大于第二个值,则将控制转移到目标指令。 |
Bgt_Un | 当比较无符号整数值或不可排序的浮点型值时,如果第一个值大于第二个值,则将控制转移到目标指令。 |
Ble | 如果第一个值小于或等于第二个值,则将控制转移到目标指令。 |
Ble_Un | 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于或等于第二个值,则将控制转移到目标指令。 |
Blt | 如果第一个值小于第二个值,则将控制转移到目标指令。 |
Blt_Un | 当比较无符号整数值或不可排序的浮点型值时,如果第一个值小于第二个值,则将控制转移到目标指令。 |
Bne_Un | 当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令。 |
Ceq | 比较两个值。如果这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;否则,将 0 (int32) 推送到计算堆栈上。 |
Cgt | 比较两个值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 |
Cgt_Un | 比较两个无符号的或不可排序的值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 |
Clt | 比较两个值。如果第一个值小于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。 |
Clt_Un | 比较无符号的或不可排序的值 value1 和 value2。如果 value1 小于 value2,则将整数值 1 (int32 ) 推送到计算堆栈上;反之,将 0 ( int32 ) 推送到计算堆栈上。 |
上面表中,以字母B开头的指令,都是比较转移指令,即从栈顶弹出两个数据,进行指定的比较运算,并按结果确定是否转移;
以C开头的,则是从堆栈弹出栈顶的两个数据进行比较,将比较结果再压入堆栈。
与高级语言比较显著的区别,是中间语言比较时,必须确定是按有符号数比较还是按无符号数比较。
其实,这还不是最麻烦的,最麻烦的是,上述指令,仅能对简单的基础数据类型,即基元类型(基元类型包括 Boolean、Byte、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、Char、Double 和 Single)进行比较运算。
比如,如果你想比较 DateTime类型、String类型、Decimal类型,则不能使用上述指令,而必须调用该类型的运算符函数来运算!
三、非基元数据类型的比较运算
如果数据类型是 DateTime、String、Decimal等类型,则需要分别处理:
1、字符串(String)类型:
a)、比较是否相等,需要调用字符串类型的 op_Equality 方法(typeof(string).GetMethod("op_Equality", new Type[] { typeof(string), typeof(string) }))
b)、不相等,需要调用字符串类型的 op_Inequality 方法,(type(string).GetMethod("op_Inequality", new Type[] { typeof(string), typeof(string) }))
c)、比较大小,需要调用字符串类型的 Compare 方法,(type(string).GetMethod("Compare", new Type[] { typeof(string), typeof(string) }))
之后,再比较调用 Compare 方法后返回值,如为0,则相等,如小于0,则第一个参数小于第二个参数,如大于0,则第一个参数大。
2、DateTime、Decimal 类型
与上面类似,等于、不等于、小于、小于等于、大于、大于等于,要分别调用该类型的 op_Equality、op_Inequality、op_LessThan、op_LessThanOrEqual、op_GreaterThan、op_GreaterThanOrEqual 等方法。
四、示例代码
下面示例,不保证100%正确,但在我目前所应用范围内尚算正确。
另,我在应用过程中,并无好的参考资料,也无人可交流,只有在反复出错中测试,或先写C#代码编译后,再以 Reflector.exe 查看 IL 代码,来逐步修正自己程序。如有朋友提供更好的实现方案,不胜感激。