亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C#當調用Remove失效時

2019-11-18 16:45:22
字體:
來源:轉載
供稿:網友

有沒有試過從一個集合里面移除一個對象之后,這個集合仍然留有這個對象?世界之大,無奇不有。稍有疏忽,便會導致這種奇怪的現象。現在讓我們看看這個“不死”對象究竟是怎么一回事。

 

1、“不死”對象現身

這個問題起初是我一個同事提出的,為了重現“不死”對象,現把代碼簡化如下:

// Code #01

IList PRoducts = new List<Product>();
products.Add(GetProduct("1412"));
products.Remove(GetProduct("1412"));
其中 Product 類代碼如下:

// Code #02

class Product
{
    public Product(string id)
    {
        m_ID = id;
    }

    private string m_ID;
    public string ID
    {
        get { return m_ID; }
    }

    public override string ToString()
    {
        return "ID: " + m_ID;
    }
}
而 GetProduct 方法則根據傳入的 ID 從數據庫讀取數據并返回,它的簽名如下:

// Code #03

public static Product GetProduct(string id);
要想知道編號為 1412 的對象是否從 products 中移除,只需在 Code #01 的最后加上這樣一行:

// Code #04

Console.WriteLine(products.Count);
 

2、一不小心掉進陷阱

不知道你有沒有查看 SDK 的習慣,其實 SDK 里面蘊藏著很多對我們解決問題有啟發作用的信息的?,F在讓我們看看 SDK 里面能否找到什么蛛絲馬跡。

由于 products 的真身是 List<T>,所以我們有必要看看 List<T> 是如何實現 IList.Remove 的:

This method determines equality using the default equality comparer EqualityComparer.Default for T, the type of values in the list.

原來,List<T> 在 IList.Remove 中使用 EqualityComparer.Default 來判斷兩個對象是否相等。那么 EqualityComparer.Default 又是如何得知兩個對象是否相等呢?

The Default property checks whether type T implements the System.IEquatable generic interface and if so returns an EqualityComparer that uses that implementation. Otherwise it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

把上面這段話結合 Code #02 來看,我們可以發現 List<T> 中的 IList.Remove 判斷兩個 Product 對象是否相等的方法是從 Object 根類繼承下來的 Equals 和 GetHashCode 方法,即比較兩個對象的引用是否指向同一個對象。

由于 GetProduct 方法每次返回的都是一個新的對象(暫時讓我們忘記對象緩存這家伙),于是就導致了集合里面出現“不死”對象。

 

3、不要被同一顆子彈打中兩次

“不要被同一顆子彈打中兩次”原意是指同一個錯誤不要兩次犯,這句話暗含著對兩個表示錯誤的對象進行邏輯上的判等,就像上面需要判斷兩個 Product 的對象在邏輯上是否相等那樣。

至此,我們也知道了令 Remove 重新生效的兩個可選辦法是:

讓 Product 類實現 IEquatable<T> 接口;
為 Product 類重寫 Equals 和 GetHashCode 方法。
在大多數情況下,我們希望比較的并不是對象的引用,而是對象的內容,與此同時,我們又不太可能為了這些小對象勞師動眾地實現對象緩存,于是,你就很有可能在類似的代碼中邂逅“不死”對象了。

posted on 2007-01-06 22:59 Allen Lee 閱讀(146) 評論(7)  編輯 收藏 引用 網摘 所屬分類: C#

 
評論
# re: 當調用 Remove 失效時 [C#] 2007-01-06 23:06 木野狐
這個問題本質上和集合無關,只是對象的判等問題,應該還是比較容易想得到原因的。  回復  更多評論   

# re: 當調用 Remove 失效時 [C#] 2007-01-06 23:17 Klesh Wong
同意樓上的,看完頭三行代碼就基本知道是怎么一回事了..  回復  更多評論   

# re: 當調用 Remove 失效時 [C#] 2007-01-06 23:30 Allen Lee
To 木野狐 and Klesh Wong:

沒錯,這個問題的本質是對象判等,但你不能說它完全與集合無關。假如這里把 Code #01 的第一行改成:

IList products = new ArrayList();

那么將只有重寫 Equals 這個方法才有效了。處理對象判等有很多方法,但不同的集合類可能會采用不同的方法。  回復  更多評論   

# re: 當調用 Remove 失效時 [C#] 2007-01-07 00:12 木野狐
@Allen Lee
剛才我用 Reflector 追溯了一下 List<T> 類的判等方法,最終追溯到了

System.Collections.Generic.EqualityComparer<T>

是這個類負責判定對象是否相等。而他有幾個子類如下:

ByteEqualityComparer,
GenericEqualityComparer<T>,
NullableEqualityComparer<T>,
ObjectEqualityComparer<T>

上面你提到的如果實現 IEquatable<T> 接口,那么最終會調用到 GenericEqualityComparer<T>, 其判等代碼如下:

public override bool Equals(T x, T y)
{
if (x != null)
{
if (y != null)
{
return x.Equals(y);
}
return false;
}
if (y != null)
{
return false;
}
return true;
}

我們可以看到,追根溯源,最終都要調用到 System.Object.Equals 方法的,而這個方法的默認實現就是和 GetHashCode 直接相關。
如果看一下其他幾個判等器(ByteEqualityComparer, NullableEqualityComparer<T>, ObjectEqualityComparer<T>),會發現情況沒有什么不同。

根據這個分析可以知道,實際上判等和集合類是沒有什么聯系的,只是集合元素類型自身的比較。并且根據 .NET 的設計規范,Equals 和 == 的語意也應該是一致的。重寫 Equals 語意的同時必然也應該重寫運算符 ==.
http://www.49028c.com/allenlooplee/archive/2007/01/06/613608.html


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本在线观看天堂男亚洲| 日韩av电影中文字幕| 欧美视频在线观看 亚洲欧| 欧美日韩在线视频一区| 欧美激情女人20p| 欧美一级在线亚洲天堂| 亚洲人成电影网站色xx| 亚洲天堂网在线观看| 国产免费一区二区三区在线能观看| 日韩欧美在线播放| 成人精品一区二区三区| 国产精品青草久久久久福利99| 欧美在线观看网站| 亚洲美女精品成人在线视频| 在线精品国产成人综合| 国产日韩在线精品av| 欧美大秀在线观看| 4388成人网| 亚洲男人天堂2024| 色偷偷噜噜噜亚洲男人的天堂| 国产91色在线|免| 成人在线小视频| 成人自拍性视频| 亚洲综合中文字幕68页| 亚洲精品有码在线| 欧美激情国产精品| 亚洲色图色老头| 成人a免费视频| 中文字幕精品一区二区精品| 成人h视频在线观看播放| 亚洲色图综合网| 国产精品爽爽爽爽爽爽在线观看| 久久久久成人精品| 在线观看国产精品91| 国产极品jizzhd欧美| 国产精品白嫩美女在线观看| 美女视频久久黄| 成人字幕网zmw| 色综合天天狠天天透天天伊人| 国语自产偷拍精品视频偷| 亚洲欧美日韩精品久久亚洲区| 伊人久久综合97精品| 成人网在线免费看| 久热精品视频在线观看一区| 亚洲综合日韩在线| 亚洲国产精品久久精品怡红院| 亚洲欧美成人在线| 国产成人一区二区在线| 91在线免费视频| 国产精品美女午夜av| 久久久久久噜噜噜久久久精品| 欧美激情视频在线免费观看 欧美视频免费一| 91免费视频网站| 欧美精品www在线观看| 国产99久久精品一区二区| 91沈先生在线观看| 亚洲一区美女视频在线观看免费| 亚洲天堂精品在线| www.xxxx精品| 欧美在线视频免费播放| 亚洲电影免费观看高清| 91精品国产综合久久香蕉的用户体验| 日本精品视频在线| 成人黄色av网站| 精品小视频在线| 亚洲欧洲日产国码av系列天堂| y97精品国产97久久久久久| 亚洲精品久久久久久久久久久久久| 精品国产乱码久久久久久天美| 97热精品视频官网| 亚洲成人免费网站| 亚洲福利在线观看| 国产精品国产亚洲伊人久久| 欧美国产在线电影| 久久亚洲欧美日韩精品专区| 91av在线国产| 国产黑人绿帽在线第一区| 91精品国产自产在线老师啪| 俺也去精品视频在线观看| 国产91精品黑色丝袜高跟鞋| 91精品国产高清久久久久久| 日韩一中文字幕| 亚洲第一av网站| 色哟哟亚洲精品一区二区| 亲子乱一区二区三区电影| 成人性生交xxxxx网站| 久久久久久久久电影| 欧美高清在线观看| 亚洲国产成人一区| 自拍偷拍亚洲精品| 国产精品久久久久影院日本| 欧美日韩性视频在线| 亚洲精品自在久久| 色偷偷av一区二区三区| 日韩中文字幕免费| 日韩在线视频中文字幕| 成人黄色av网站| 日韩精品久久久久| 久久成人免费视频| 4388成人网| 欧美成在线视频| 成人观看高清在线观看免费| 亚洲电影天堂av| 亚洲性xxxx| 国产91成人在在线播放| 亚洲色图综合网| 久久精品2019中文字幕| 日韩福利视频在线观看| 日本韩国欧美精品大片卡二| 久久久久久久999精品视频| 欧美视频国产精品| 国产日本欧美在线观看| 欧美电影免费观看电视剧大全| 欧美裸身视频免费观看| 欧美性xxxx18| 国产视频在线观看一区二区| 久久天天躁狠狠躁老女人| 青青a在线精品免费观看| 久久精品视频播放| 成人久久久久久久| www日韩中文字幕在线看| 在线观看国产成人av片| 亚洲自拍偷拍区| 欧美性猛交xxxx久久久| 成人午夜在线视频一区| 欧美精品videosex性欧美| 日本欧美一二三区| 久久久久久久av| 国产999精品视频| 精品久久久久久久久久国产| 日韩成人中文电影| 国产精品主播视频| 一级做a爰片久久毛片美女图片| 日韩一区二区三区国产| 国产精品久久999| 欧美猛男性生活免费| 亚洲成人网在线观看| 国产精品一区av| 97精品一区二区三区| 91精品久久久久久久久久久久久久| 日韩大片在线观看视频| 欧美性猛交xxx| 欧美精品videosex极品1| 亚洲国产私拍精品国模在线观看| 精品亚洲一区二区| 欧美激情在线一区| 日韩暖暖在线视频| 成人国产精品一区二区| 欧美午夜片在线免费观看| 日韩欧美大尺度| 色综久久综合桃花网| 91免费高清视频| 久久成人人人人精品欧| 狠狠操狠狠色综合网| 亚洲午夜女主播在线直播| 欧美日韩一区二区在线| 国产精品第2页| 欧美成人在线网站| 亚洲成人精品视频在线观看| 久久成人在线视频| 久久久久免费精品国产| 亚洲bt欧美bt日本bt| 亚洲国产成人精品久久久国产成人一区| 国产精品视频一区二区高潮|