操作符重載
CLR對操作符的含義一無所知,但規定了語言如何公開操作符重載的方法
需要是public static的
需要包含operator關鍵字以及對應的操作符符號
比如 + 操作符重載
public sealed class Complex
{
public static Complex operator+(Complex c1, Complex c2)
{
return null;
}
}.method public hidebysig specialname static
class CLR_Ch8.Complex op_Addition(class CLR_Ch8.Complex c1,
class CLR_Ch8.Complex c2) cil managed
{
// 程式碼大小 7 (0x7)
.maxstack 1
.locals init (class CLR_Ch8.Complex V_0)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
} // end of method Complex::op_Addition編譯器為名為op_Addition的方法生成元數據方法定義項,並設置了specialname標志
C#編譯器在看到 + 操作符後,會檢查是否有一個操作數的類型定義了名為 op_Addition的specialname方法
如果方法存在,且參數兼容於操作數的類型,就生成調用該方法的代碼
C#一元操作符及相容CLS方法名
C#操作符 特殊方法名 相容於CLS的方法名 + op_UnaryPlus Plus – op_UnaryNegation Negate ! op_LogicalNot Not ~ op_OnesComplement OnesComplement ++ op_Increment Increment — op_Decrement Decrement (無) op_True IsTrue{ get; } (無) op_False IsFalse{ get; }
C#二元操作符及相容CLS方法名
C#操作符 特殊方法名 相容於CLS的方法名 + op_Addition Add – op_Subtraction Subtract * op_Multiply Multiply / op_Division Divide % op_Modulus Mod & op_BitwiseAnd BitwiseAnd | op_BitwiseOr BitwiseOr ^ op_ExclusiveOr Xor << op_LeftShift LeftShift >> op_RightShift RightShift == op_Equality Equals != op_Inequality Equals < op_LessThan Compare > op_GreaterThan Compare <= op_LessThanOrEqual Compare >= op_GreaterThanOrEqual Compare
轉換操作符
如果源對象和目標都是編譯器識別的基元類型,編譯器自己就知道如何生成轉換對象所需的代碼
如果源對象或目標不是編譯器識別的基元類型,編譯器會生成代碼,要求CLR執行轉換(強制轉型)
CLR會檢查源對象類型和目標類型是不是相同
但是如果要把一個類型轉換成完全不同的類型,就需要定義相關的轉換方法
這個類型要有一些成員:
接收一個參數的公共構造器,讓參數類型隱式轉換自己
無參的公共實例方法,把自己顯式轉換成其他類型
具體的轉換操作符重載方法
必須是public static
參數類型和返回類型二者必有其一與定義轉換方法的類型相同
隱式轉換方法:public static implict operator 目標類型(源類型)
只有在轉換不損失精度的情況下可以定義
顯式轉換方法:public static explict operator 目標類型(源類型)
如果轉換會損失精度,需要定義顯式轉換
C#
public sealed class Rational
{
public Rational(int num) { }
public Rational(float num) { }
public int ToInt() { return default; }
public float ToFloat() { return default; }
//int/float 隱式轉型至 Rational
public static implicit operator Rational(int num)
{
return new Rational(num);
}
public static implicit operator Rational(float num)
{
return new Rational(num);
}
//Rational 顯式轉型 int/float
public static explicit operator int(Rational r)
{
return r.ToInt();
}
public static explicit operator float(Rational r)
{
return r.ToFloat();
}
}
metadata
C#編譯器檢測到代碼的轉型後,會生成IL來調用定義好的轉換操作符方法
如果代碼正使用某類型對象,但實際期望是另一個類型,編譯器會查找能執行這種轉換的隱式轉換操作符方法,並在IL中生成調用代碼
如果編譯器看到代碼存在顯式轉換,就會查找能行這種轉換的「隱式/顯式」轉換操作符方法,如果找到一個,就生成IL調用
使用C#的as 或 is操作符時,永遠不會調用這些定義的轉換方法
參考書目
- 《CLR via C#》(第4版) Jeffrey Richter