使類的擴充套件更簡單 擴充套件方法

2022-04-06 11:19:16 字數 2976 閱讀 5784

1、什麼是擴充套件方法?

擴充套件方法,首先是一種方法,它可以用來擴充套件已定義型別中的方法成員。

在擴充套件方法誕生之前,如果想為乙個已有型別自定義含有特殊邏輯的新方法時,你必須重新定義乙個型別來繼承已有型別,以這種方式來新增方法。如果基類有抽象方法,則還要重新去實現這個抽象方法。

這樣,為了擴充套件乙個方法,需要承擔更多的因繼承而產生的開銷。使用繼承來擴充套件現有型別總有點大材小用的感覺,並且值型別或密封類(不能被繼承的類)等也不能被繼承,不能由此獲得擴充套件。

於是,c#3.0提出了擴充套件方法。

2、擴充套件方法的使用

2.1 定義擴充套件方法

1

public

static

class

listextern29

int jsum = 0;10

bool flag = false;11

12foreach (var i in

source)

1319

else

2023}24

return

jsum;25}

26 }

在以上**中,jsum方法就是乙個擴充套件方法,它的功能是計算陣列中小標為奇數的陣列成員之和。並不是所有的方法都可以用作擴充套件方法。下列是符合擴充套件方法的定義規則:

(1)擴充套件方法必須在乙個非巢狀、非泛型的靜態類中定義;

(2)它至少要有乙個引數;

(3)第乙個引數必須加上this關鍵字作為字首(第乙個引數型別也稱為擴充套件型別,即指方法對這個型別進行擴充套件);

(4)第乙個引數不能使用任何其他的修飾符(如不能使用ref、out等修飾符);

(5)第乙個引數的型別不能是指標型別。

這些規則都是硬性規定,無論方法違反了哪一條,編譯器都可能會報錯,或認為它不是乙個擴充套件方法。

2.2 呼叫擴充套件方法

成功定義了乙個擴充套件方法後,接下來就該去呼叫它。

1

static

void main(string

args)2;

4int jsum =source.jsum();

5 console.writeline("

陣列的奇數和為:

"+jsum);

6console.readkey();

7 }

成功呼叫,說明了擴充套件方法呼叫的獨特性,即這裡可以直接通過list型別來呼叫擴充套件方法。

3、編譯器如何發現擴充套件方法

對於c# 3.0編譯器而言,當它看到某個型別的變數在呼叫方法時,它會首先去該物件的例項方法中進行查詢,如果沒有找到與呼叫方法同名並引數一致的例項方法,編譯器就回去查詢存在合適的擴充套件方法。

編譯器會檢查所有匯入的命名控制項和當前命名控制項中的擴充套件方法,並將變數型別匹配到擴充套件型別,這裡存在乙個隱式轉換的擴充套件方法。如在前面**中,從list到我們擴充套件的型別ienumerable就存在乙個隱式轉換。

從編譯器發現擴充套件方法的過程來看,方法呼叫的優先順序順序應為:型別例項方法-當前命名空間下的擴充套件方法-匯入命名控制項的擴充套件方法。下面就用**來演示一下編譯器發現方法的過程:

1

namespace

擴充套件方法22;

9p.print();

10 p.print("

hello");

11}12}

1314

public

class

person

1517}18

19public

static

class

extensionclass20"

);24}25

}26}27

28namespace

擴充套件方法329"

);37}38

39public

static

void print(this person per,string

s)40

,附加字串");

42}43}

4445 }

在以上**中,存在兩個不同的命名控制項,她們都定義了帶乙個引數的擴充套件方法print。根據前面對編譯器呼叫方法的優先順序的分析,編譯器首先檢視person型別中是否定義了無參的print例項方法。如果有,則停止查詢;否則繼續查詢當前命名空間下,即currentnamespace下是否定義了帶乙個引數的擴充套件方法print。

注意:(1)如果擴充套件的型別中定義了無引數的print的例項方法,則在p後面鍵入「.」運算子時,vs的智慧型提示將不會給出擴充套件方法。

(2)如果同乙個命名空間下的兩個類中含有擴充套件型別相同的方法,編譯器便不知道該呼叫哪個方法了,就會出現編譯錯誤。

4、空引用也可呼叫擴充套件方法

4.1 拿例子說話

1

namespace

擴充套件方法32"

);10

console.readkey();11}

12}1314

public

static

class

nullextern

1520

}21 }

以上的**沒有報異常,可以正常執行。不過在上面的**中,**擴充套件了object型別,所有繼承於object的型別都將具有該擴充套件方法,這就對其他子型別產生了「汙染」。

更好的實現方式應該是:

1

public

static

bool isnull(this

string

str)

2

所以當我們為某乙個型別定義擴充套件方法時,應盡量擴充套件具體的型別,而不要擴充套件其基類。在空引用上呼叫擴充套件方法之所以不會出現nullreferenceexception異常,是因為對於編譯器而言,這個過程只是把空引用"s"當成引數傳入靜態方法而已,即s.isnull的呼叫等效於下面**:console.writeline($"字串s為空字串");這並不是真正地在空引用上呼叫方法,所以也就不存在異常的問題。

php spl 擴充套件,PHP SPL擴充套件庫簡單使用

1.autoload 這是乙個自動載入函式,在php5中,當我們例項化乙個未定義的類時,就會觸發此函式。看下面例子 myclass.php class myclass public function construct echo myclass init ed successfuly index.p...

C 類擴充套件方法

擴充套件方法使你能夠向現有型別 新增 方法,而無需建立新的派生型別 重新編譯或以其他方式修改原始型別。擴充套件方法是一種特殊的靜態方法,但可以像擴充套件型別上的例項方法一樣進行呼叫下面以乙個 例子說明 定義乙個npc 類 定義 npc 類 public class npc 定義字段變數對應的屬性 p...

擴充套件方法的簡單介紹

在說擴充套件方法之前先說乙個例子 把集合中字串小於 7 查詢出來,然後列印 static void main string args var temp list.where a a.compareto 7 0 foreach var item in temp console.readkey wher...