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