3 回答

TA貢獻(xiàn)1866條經(jīng)驗(yàn) 獲得超5個(gè)贊
IEnumerable作為參數(shù)的問題在于它告訴呼叫者“我希望枚舉這個(gè)”。它沒有告訴他們你想要枚舉多少次。
我可以將objects參數(shù)更改為L(zhǎng)ist,然后避免可能的多次枚舉,但后來我沒有得到我能處理的最高對(duì)象。
采取最高目標(biāo)的目標(biāo)是高尚的,但它為太多的假設(shè)留下了空間。你真的希望有人將LINQ to SQL查詢傳遞給這個(gè)方法,只為你枚舉它兩次(每次得到可能不同的結(jié)果嗎?)
這里缺少的語義是,調(diào)用者可能沒有花時(shí)間閱讀方法的細(xì)節(jié),可能假設(shè)您只迭代一次 - 因此他們會(huì)傳遞給您一個(gè)昂貴的對(duì)象。您的方法簽名不表示任何一種方式。
通過將方法簽名更改為IList/ ICollection,您至少可以使調(diào)用者更清楚您的期望是什么,并且可以避免代價(jià)高昂的錯(cuò)誤。
否則,大多數(shù)查看該方法的開發(fā)人員可能會(huì)假設(shè)您只迭代一次。如果采取一個(gè)IEnumerable非常重要的,你應(yīng)該考慮.ToList()在方法的開頭做。
遺憾的是.NET沒有IEnumerable + Count + Indexer的接口,沒有Add / Remove等方法,這是我懷疑會(huì)解決這個(gè)問題的方法。

TA貢獻(xiàn)2065條經(jīng)驗(yàn) 獲得超14個(gè)贊
如果您的數(shù)據(jù)總是可重復(fù)的,也許不用擔(dān)心。但是,您也可以將其展開 - 如果傳入的數(shù)據(jù)很大(例如,從磁盤/網(wǎng)絡(luò)讀?。@尤其有用:
if(objects == null) throw new ArgumentException();
using(var iter = objects.GetEnumerator()) {
if(!iter.MoveNext()) throw new ArgumentException();
var firstObject = iter.Current;
var list = DoSomeThing(firstObject);
while(iter.MoveNext()) {
list.Add(DoSomeThingElse(iter.Current));
}
return list;
}
注意我稍微改變了DoSomethingElse的語義,但這主要是為了顯示展開的用法。例如,您可以重新包裝迭代器。你也可以把它變成一個(gè)迭代器塊,這可能很好; 然后沒有l(wèi)ist- 你會(huì)yield return得到它們的項(xiàng)目,而不是添加到要返回的列表。

TA貢獻(xiàn)1841條經(jīng)驗(yàn) 獲得超3個(gè)贊
在方法簽名中使用IReadOnlyCollection<T>或IReadOnlyList<T>代替IEnumerable<T>,可以明確表示您可能需要在迭代之前檢查計(jì)數(shù),或者由于某些其他原因而多次迭代。
但是,如果您嘗試重構(gòu)代碼以使用接口,它們會(huì)產(chǎn)生很大的缺點(diǎn),例如使其更易于測(cè)試并且對(duì)動(dòng)態(tài)代理更友好。關(guān)鍵點(diǎn)在于,IList<T>它不會(huì)繼承IReadOnlyList<T>,也類似于其他集合及其各自的只讀接口。(簡(jiǎn)而言之,這是因?yàn)?NET 4.5希望保持ABI與早期版本的兼容性。但他們甚至沒有機(jī)會(huì)在.NET核心中改變它。)
這意味著如果你IList<T>從程序的某些部分得到一個(gè)并希望將它傳遞給另一個(gè)期望的部分IReadOnlyList<T>,你就不能!但是你可以傳遞IList<T>一個(gè)IEnumerable<T>。
最后,IEnumerable<T>是所有.NET集合支持的唯一只讀接口,包括所有集合接口。任何其他選擇都會(huì)回來咬你,因?yàn)槟阋庾R(shí)到你把自己鎖定在某些架構(gòu)選擇之外。所以我認(rèn)為在函數(shù)簽名中使用它是正確的類型來表示你只需要一個(gè)只讀集合。
(請(qǐng)注意,IReadOnlyList<T> ToReadOnly<T>(this IList<T> list)如果底層類型支持兩個(gè)接口,您總是可以編寫一個(gè)簡(jiǎn)單強(qiáng)制轉(zhuǎn)換的擴(kuò)展方法,但是您必須在重構(gòu)時(shí)手動(dòng)添加它,而且IEnumerable<T>總是兼容的。)
一如既往,這不是絕對(duì)的,如果你正在編寫數(shù)據(jù)庫密集的代碼,意外的多次枚舉將是一場(chǎng)災(zāi)難,你可能更喜歡不同的權(quán)衡。
- 3 回答
- 0 關(guān)注
- 440 瀏覽
添加回答
舉報(bào)