国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

編寫(xiě)高質(zhì)量代碼改善C#程序的157個(gè)建議——建議18:foreach不能代替for

2019-11-14 14:07:02
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

建議18:foreach不能代替for

上一個(gè)建議中提到了foreach的兩個(gè)優(yōu)點(diǎn):語(yǔ)法更簡(jiǎn)單,默認(rèn)調(diào)用Dispose方法,所有我們強(qiáng)烈建議在實(shí)際的代碼編寫(xiě)中更多的使用foreach。但是,該建議也有不適合的場(chǎng)景。

foreach存在一個(gè)問(wèn)題:它不支持循環(huán)時(shí)對(duì)集合進(jìn)行增刪操作。比如,運(yùn)行下面代碼會(huì)拋出異常InvalidOperationException:

            List<int> list=new List<int>(){0,1,2,3};            foreach (int item in list)            {                list.Remove(item);                Console.WriteLine(item);            }

取而代之的方法是使用for循環(huán)

            for (int i = 0; i < list.Count; i++)            {                list.Remove(list[i]);                Console.WriteLine(list[i]);            }

foreach循環(huán)使用了迭代器進(jìn)行集合的遍歷,它在FCL提供的跌代替內(nèi)部維護(hù)了一個(gè)對(duì)集合版本的控制。那么什么是集合版本?簡(jiǎn)單來(lái)說(shuō),其實(shí)它就是一個(gè)整形的變量,任何對(duì)集合的增刪操作都會(huì)使版本號(hào)加1.foreach會(huì)調(diào)用MoveNext方法來(lái)遍歷元素,在MoveNext方法內(nèi)部會(huì)進(jìn)行版本號(hào)的檢測(cè),一旦檢測(cè)到版本號(hào)有變動(dòng),就會(huì)拋出InvalidOperationException異常。

如果使用for循環(huán)就不會(huì)帶來(lái)這樣的問(wèn)題。for直接使用索引器,它不對(duì)集合版本號(hào)進(jìn)行判斷,所以不會(huì)存在以為集合的變動(dòng)而帶來(lái)的異常(當(dāng)然,超出索引長(zhǎng)度這種異常情況除外)。

由于for循環(huán)和foreach循環(huán)實(shí)現(xiàn)上有所不同(前者索引器,后者迭代器),因此關(guān)于兩者性能上的爭(zhēng)議從來(lái)沒(méi)有停止過(guò)。但是,即使有爭(zhēng)議,雙方都承認(rèn)兩者在時(shí)間和內(nèi)存上有損耗,尤其是針對(duì)泛型集合時(shí),兩者的損耗是在同一個(gè)數(shù)量級(jí)別上的。

以類(lèi)型List<T>為例,索引器如下所示:

[__DynamicallyInvokable]public T this[int index]{    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable]    get    {        if (index >= this._size)        {            ThrowHelper.ThrowArgumentOutOfRangeException();        }        return this._items[index];    }    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable]    set    {        if (index >= this._size)        {            ThrowHelper.ThrowArgumentOutOfRangeException();        }        this._items[index] = value;        this._version++;    }}

迭代器如下所示:

[__DynamicallyInvokable]public bool MoveNext(){    List<T> list = this.list;    if ((this.version == list._version) && (this.index < list._size))    {        this.current = list._items[this.index];        this.index++;        return true;    }    return this.MoveNextRare();}
[__DynamicallyInvokable]public T Current{    [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]    get    {        return this.current;    }} 

可以看到,List<T>類(lèi)內(nèi)部維護(hù)著一個(gè)泛型數(shù)組:

PRivate T[] _items;

無(wú)論是for循環(huán)還是foreach循環(huán),內(nèi)部都是對(duì)該數(shù)組的訪問(wèn),而迭代器僅僅是多進(jìn)行了一次版本檢測(cè)。事實(shí)上,在循環(huán)內(nèi)部,兩者生成的IL代碼也是差不多的,但是,正如本建議剛開(kāi)始提到的那樣,因?yàn)榘姹緳z測(cè)的緣故,foreach循環(huán)并不能代替for循環(huán)。

 

 

轉(zhuǎn)自:《編寫(xiě)高質(zhì)量代碼改善C#程序的157個(gè)建議》陸敏技

 


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 炉霍县| 乳山市| 克什克腾旗| 民丰县| 张家口市| 大英县| 邵阳县| 德昌县| 大名县| 白沙| 孝昌县| 建德市| 商南县| 屏东县| 涿鹿县| 丰顺县| 广丰县| 玉龙| 兴宁市| 闽侯县| 白沙| 汾西县| 迭部县| 苏州市| 武宣县| 永昌县| 堆龙德庆县| 平泉县| 米脂县| 固原市| 东城区| 礼泉县| 开鲁县| 台南县| 越西县| 正定县| 通河县| 扬中市| 和静县| 六枝特区| 宁强县|