天天看點

運算符重載方法,擴充方法,以及方法參數

運算符重載方法

一 些程式設計語言允許定義運算符如果操作類型的執行個體,例如System.String,System.Decimal,和System.DateTime,它們 重載了==和!=運算符。但是對于CLR來說,它是完全不知道像“==”和“!=”這些運算符是幹什麼的。程式設計語言定義了每一種運算符的意義以及當這些運 算符的符号出現時應該生成什麼樣的代碼。例如C#裡面,數值類型的當遇到“+”這個符号時,在編譯時會生成将兩個number加起來的代碼,如果是 String類型遇到,則會将兩個字元串拼接起來。

CLR指定運算符重載方法必須是public和static,并且C#要求運算符方法的參數中至少有一個參數的類型跟運算符方法定義的類型一緻。這樣做的原因是:它能夠讓C#編譯器在一個合理的時間期限找到該運算符綁定的方法。例如:

這樣寫會報這樣的錯誤:元運算符的參數之一必須是包含類型,修正如下:

編譯器會生成定義了入口的op_Addition方法,這個方法也具有specialname标 志,表明它是一個特殊的方法。當編譯器發現了“+”運算符時,它會去檢查是否存在一個标記了specialname的op_Addition方法的參數的 類型跟操作數的類型相容。如果存在這樣的方法,編譯器會生成調用該方法的代碼,如果不存在,則報錯。

下面展示了C#中一進制和二進制運算符對應的CLS方法名:

運算符重載方法,擴充方法,以及方法參數

View Code

運算符重載是非常有用的工具,可以讓開發者用簡潔的代碼來表達思想。然而,并不是所有的程式設計語言都支援運算符重載。當使用不支援運算符重載的語言時,編譯器會報錯。此時應該允許直接調用如op_Addition這樣的方法。在C#裡面,不能直接調用op_Addition方法。當C#編譯器檢測到“+”運算符時,會尋找具有sepecialname标記的op_Addition方法。

擴充方法

擴充方法提供了這樣一種調用方式,那就是使用執行個體方法的調用文法來調用一個靜态方法。定義擴充方法的文法是對擴充的類型使用this關鍵字。如:

這是可以這樣調用sb.IndexOf('X'),編譯器首先會檢查StringBuilder類或它的 基類是否提供了該執行個體方法。如果存在則編譯生成IL代碼調用。如果沒有比對的執行個體方法,則編譯器則會查找任何定義了靜态的IndexOf方法的靜态類,并 且該靜态的IndexOf方法接收一個跟發起調用的表達式的類型比對,該類型必須通過this關鍵字标記。上面的例子中表達式是sb,類型是 StringBuilder。編譯器會查找接收兩個參數:StringBuilder(this标記)和Char類型的參數的IndexOf方法。

命名參數和可選參數需要注意的幾個部分

1.可以指定方法的參數的預設值,以及作為參數的委托的預設值。

2.具有預設值的參數必須在沒有預設值參數的右邊。

3.預設值在編譯時必須是常量值

4.不能為ref和out類型的參數設定預設值

ref和out區分

1.預設情況下,CLR假定所有方法的參數都是通過值傳遞

2.從CLR的角度看,ref和out是一樣的,生成相同的IL,傳遞都是對象的位址。中繼資料除了一位不同(用來區分是out還是ref),其他也一樣。

3.C#對待ref和out是不同的方式:

  ①對于out,調用之前不用初始化,但是ref在調用之前必須初始化

  ②對于out,在傳回之前必須給out參數指派,而ref參數則不用

params參數數組

當傳遞很多個同類型的參數時,可以考慮使用參數數組。params關鍵字告訴編譯器對該參數應用一個System.ParamArrayAttribute的執行個體。

C#編譯器檢測到調用一個方法時,它會檢查所有指定名稱的方法,這時是針對不帶ParamArray特性的參數方法。如果有比對的,則調用。如果沒有,則

查找具有ParamArray特性參數的方法,檢查是否滿足。如果能夠比對,則生成構造數組的代碼并填充沒一個元素,這是在調用選中的方法之前進行的。

隻有最後一個參數能夠标記為params。調用一個接收參數數組的方法會增加額外的性能消耗,當然如果顯示的傳遞null則不會。是以應該盡可能少的使用參數數組傳遞。

關于參數類型和傳回值類型的選擇建議

1.對于方法的參數類型,盡量選擇包容性強的類型。例如選擇IList<T>類型替代List<T>類型,因為這樣除了可以傳遞IList<T>類型,還可以傳遞任何實作了該接口IList<T>的類型參數。

2.對于方法的傳回值,盡量使用更具體的類型。例如選擇FileSteam替代Stream。這樣友善我們對調用方法之後,能夠在更直接的在小範圍處理傳回結果。

注   《CLR via C#》(Jeffrey Richter著)——.NET 界的經典之作,讀的過程寫點筆記跟大家分享,我也推薦大家看英文版,能夠直接領會原意 

繼續閱讀