System.Decimal 类型是个特殊的类型,他并不直接属于CLR IL的基本类型,而是C#语言自己定义的。(其他值类型比如System.Int32都有对应的IL类型int32)
因此可以通过Reflector查看关于操作符重载和转换操作符的方法
1. 操作符重载
Code
//正:+decimal1
public static decimal operator +(decimal d)
{
return d;
}
//负:-decimal1
public static decimal operator -(decimal d)
{
return Negate(d);
}
//自增:decimal1++
public static decimal operator ++(decimal d)
{
return Add(d, 1M);
}
//自减:decimal1--
public static decimal operator --(decimal d)
{
return Subtract(d, 1M);
}
//加法 decimal1 + decimal2
public static decimal operator +(decimal d1, decimal d2)
{
return Add(d1, d2);
}
2. 转化操作符
Code
//隐式转化: int i =2; decimal d1 = i;
public static implicit operator decimal(int value)
{
return new decimal(value);
}
//显示转化:decimal d1 = 2.32; short s1 = (short)d1;
public static explicit operator short(decimal value)
{
return ToInt16(value);
}
3. 实际上,上述操作符重载方法最终将编译成普通IL方法。
c#编译器在源码中看到一个+号时,会去查看是否定义了一个op_Addition的方法(对应+操作符)并检查参数类型是否兼容。
而对于隐式转化,将分别编译成op_Implicit的不同重载方法(overload)
显式转化编译成op_Explicit的不同重载方法,而且是C#不支持但CLR支持的同名同参数不同返回值类型方法。
Code
//ILDASM 查看decimal的加号重载
.method public hidebysig specialname static
valuetype System.Decimal op_Addition(valuetype System.Decimal d1,
valuetype System.Decimal d2) cil managed
{
// 代码大小 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call valuetype System.Decimal System.Decimal::Add(valuetype System.Decimal,
valuetype System.Decimal)
IL_0007: ret
} // end of method Decimal::op_Addition
//从Int64隐式转化为decimal方法的IL代码
.method public hidebysig specialname static
valuetype System.Decimal op_Implicit(int64 'value') cil managed
{
// 代码大小 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void System.Decimal::.ctor(int64)
IL_0006: ret
} // end of method Decimal::op_Implicit
//从char隐式转化为decimal方法的IL代码
.method public hidebysig specialname static
valuetype System.Decimal op_Implicit(char 'value') cil managed
{
// 代码大小 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void System.Decimal::.ctor(int32)
IL_0006: ret
} // end of method Decimal::op_Implicit
//显式转化为Double型方法的IL代码 注意返回类型是float64即C#中double
.method public hidebysig specialname static
float64 op_Explicit(valuetype System.Decimal 'value') cil managed
{
// 代码大小 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call float64 System.Decimal::ToDouble(valuetype System.Decimal)
IL_0006: ret
} // end of method Decimal::op_Explicit
//显式转化为Int32.与上面相比函数定义只有返回类型不同
.method public hidebysig specialname static
int32 op_Explicit(valuetype System.Decimal 'value') cil managed
{
// 代码大小 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call int32 System.Decimal::ToInt32(valuetype System.Decimal)
IL_0006: ret
} // end of method Decimal::op_Explicit