第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

處理可能多次枚舉IEnumerable的警告

處理可能多次枚舉IEnumerable的警告

子衿沉夜 2019-08-30 15:08:27
在我的代碼中需要使用IEnumerable<>幾次因此得到Resharper錯(cuò)誤“可能的多個(gè)枚舉IEnumerable”。示例代碼:public List<object> Foo(IEnumerable<object> objects){    if (objects == null || !objects.Any())        throw new ArgumentException();    var firstObject = objects.First();    var list = DoSomeThing(firstObject);            var secondList = DoSomeThingElse(objects);    list.AddRange(secondList);    return list;}我可以更改objects參數(shù)List,然后避免可能的多次枚舉,但后來我沒有得到我能處理的最高對(duì)象。我可以做的另一件事是將轉(zhuǎn)換IEnumerable到List在方法的開頭: public List<object> Foo(IEnumerable<object> objects) {    var objectList = objects.ToList();    // ... }但這只是尷尬。在這種情況下你會(huì)做什么?
查看完整描述

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è)問題的方法。


查看完整回答
反對(duì) 回復(fù) 2019-08-30
?
翻翻過去那場(chǎng)雪

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)目,而不是添加到要返回的列表。


查看完整回答
反對(duì) 回復(fù) 2019-08-30
?
偶然的你

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)衡。


查看完整回答
反對(duì) 回復(fù) 2019-08-30
  • 3 回答
  • 0 關(guān)注
  • 440 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)