2014-09-19 50 views
2

我有一種場景,其中IEnumerable.SequenceEqual擴展方法返回false時,我不期望它 - 確切地說,當使用它來比較兩套(已知相同)ILookup<int, int>。通過調試器,我發現我的兩個集合中的實際元素是Lookup<TKey, TElement>.Grouping類的實例,所以我跳入了參考源。爲什麼Lookup <TKey,TValue> .Grouping類不提供相等覆蓋?

要長話短說,SequenceEqual使用的默認相等比較器是ObjectEqualityComparer,默認使用標準Object.Equals。但Lookup<TKey, TElement>.Grouping不會覆蓋Equals,所以ObjectEqualityComparer最終使用默認Object.Equals方法,它調用到RuntimeHelpers.Equals,這(我想,因爲它是extern)做參考比較和返回false。

我看不出有什麼好的理由,爲什麼粗體部分應該是真的,因此這個問題。有人知道(或者可以解釋)這是否是一個故意的設計決定(如果是這樣,爲什麼) - 或者它只是一個無意的遺漏?

回答

2

公開地,Lookup<TKey, TElement>.Grouping只是一個IEnumerable<TElement>

一般而言,兩個IEnumerable<TElement>實例是而不是等於僅僅因爲它們的元素相等。

爲什麼IEnumerable<TElement>的這個特定實現有所不同?

+0

「...兩個IEnumerable 實例因爲它們的元素相等而不相等,爲什麼IEnumerable 的這個特定實現有所不同?當你用這些術語來表達時,這是完全合理的。 – 2014-09-19 14:02:26

1

BCL中的任何收藏都會覆蓋相等成員。這是他們堅持的慣例

爲什麼?猜測:性能概況可能會令人驚訝。或者,他們認爲參考比較會更有用。或者,他們發現無法在任何地方定義合適的平等(例如MatchCollection)。所以他們決定至少是一致的

我沒有看到任何理由爲什麼IGrouping將是一個特別有用的平等方法的候選人。與其他任何收藏一樣,它的用處非常有用。

給自己寫一個CollectionEqualityComparer<T>並在任何地方重複使用。

0

如果一個類是可變的,該類型的任何特定變量或存儲位置可以封裝任何的幾件事情:

  1. 在宇宙中的任何地方的唯一參考那個類的一個實例。

  2. 對每個人都被禁止修改的類的實例的引用。

  3. 對該類的實例的引用,其中可能存在其他引用,但由變量或存儲位置的所有者擁有,並且不會在所有者不知情的情況下進行修改。

  4. 對其他人擁有的該類實例的引用,並且可能在不知道變量或存儲位置所有者的情況下進行修改。

在前兩種情況下,基於價值的等價性通常是合適的。在第三種情況下,它可能也可能不適合(取決於外部參考的語義重要性)。在第四種情況下,基於價值的等值是不合適的。不幸的是,即使幾乎所有的變量和存儲位置都可以通過編寫代碼的人很容易地分類到上述類別之一中,但是沒有定義的機制來使得該信息對於編譯器和運行時可用。因此,沒有任何機制可以在適當情況下使用基於價值的等同原則,而不適用時也不會採用這種機制。

相關問題