你能指出這個 ForEach 擴充套件方法中的錯誤嗎?

2021-09-07 23:39:01 字數 2473 閱讀 3801

linq 中沒有原生的 foreach 擴充套件方法,我們可以很輕鬆的擴充套件乙個:

1

23

public

static void foreach(this ienumerablesource, actionaction)

上面這個 foreach 是沒有返回值的,寫完 foreach 本句**也就結束了,這與 linq 鏈式程式設計風格是不符的。

細心檢視的話,你會發現 enumerble 和 queryable 中的每個擴充套件方法都是有返回值的,這樣才能保證**鏈鏈不斷。

改進下,讓 foreach 返回 ienumerable,相信不少朋友會錯誤地寫出如下的**:

123

4

public

static ienumerableforeach(this ienumerablesource, actionaction)

我們來測試下這個擴充套件方法,先寫第乙個測試:

123

4567

891011

1213

1415

16

public

class employee

public

decimal bonus

}[testmethod()]

public

void foreachtest() ,

new employee

};var actualbonus = employees

.foreach(e => e.bonus += 200)

.first(e => e.name == "李四")

.bonus;

assert.areequal(1000, actualbonus);

}

說明:在 .net framework 2.0 版中,array 類實現 system.collections.generic.ilist、system.collections.generic.icollection 和 system.collections.generic.ienumerable 泛型介面。

由於實現是在執行時提供給陣列的,因而對於文件生成工具不可見。

因此,泛型介面不會出現在 array 類的宣告語法中,也不會有關於只能通過將陣列強制轉換為泛型介面型別(顯式介面實現)才可訪問的介面成員的參考主題。

將某一陣列強制轉換為這三種介面之一時需要注意的關鍵一點是,新增、插入或移除元素的成員會引發 notsupportedexception。

摘自:

這個測試是可以順利通過的,但不能說明**是正確的,我們再來寫乙個測試。

enumerable.range 方法 可以生成整數序列,我們就呼叫它來作為 source 引數:

123456

[testmethod()]

public

void foreachtest2()

第 4 行僅為了測試,其它情況下使用 select(i => i*10) 更為恰當。

這次測試通不過了:

應該思考下了,自已動腦解決 勝過 他人直接告知 。

再給出最後乙個測試,看了基本就能找出錯誤所在了:

123

4567

891011

1213

14

public ienumerablegetemployees() ;

yield return

new employee ;

}[testmethod()]

public

void foreachtest3()

通過上面幾個測試,應該發現 yield 的特性會讓上面的 foreach 出問題,請參看 artech 的文章 《 從yield關鍵字看ienumerable和collection的區別 》進行更深入的了解。

如果你使用的是 iqueryable問題可能出現,要考慮一些 orm 框架的快取情況。

那麼怎麼正確實現 foreach 擴充套件方法呢,我想還是留給大家來思考完成吧,一味接受可不是好的學習方式。

另外,還可以實現如下簽名的擴充套件,以方便使用:

1
public

static ienumerableforeach(this ienumerablesource, actionint> action)

有關 linq 中為什麼沒有原生的的 foreach 擴充套件的討論,請參見文章:

Scala 中的foreach和map方法比較

scala中的集合物件都有foreach和map兩個方法。兩個方法的共同點在於 都是用於遍歷集合物件,並對每一項執行指定的方法。而兩者的差異在於 foreach無返回值 準確說返回void map返回集合物件。見如下 及執行結果 b.getclass 得到的是void,而c.getclass得到的是...

Scala 中的foreach和map方法比較

scala中的集合物件都有foreach和map兩個方法。兩個方法的共同點在於 都是用於遍歷集合物件,並對每一項執行指定的方法。而兩者的差異在於 foreach無返回值 準確說返回void map返回集合物件。見如下 及執行結果 b.getclass 得到的是void,而c.getclass得到的是...

C 中的擴充套件方法

c 中的擴充套件方法用來為現有型別新增方法,以擴充套件現有的型別,這些型別可以是基本的資料型別 如int string等 也可以是自己定義的型別。擴充套件方法是通過指定關鍵字this修飾方法的第乙個引數而宣告的。擴充套件方法只可以宣告在靜態類中。以下為擴充套件基本型別string public st...