[英]C# Struct dictionary key not working with array member
我正在嘗試創建一個在構造過程中采用可變數量參數的結構,目的是將此對象用作字典鍵(我的.Net版本不支持Tuple
類型):
struct TupleKey
{
int[] args;
public TupleKey(params int[] args) { this.args = args; }
}
但是,當我將此struct
用作字典的鍵時, ContainsKey
方法將返回false。
var d = new Dictionary<TupleKey, int>();
d.Add(new TupleKey(1, 1), 1);
Console.WriteLine(d.ContainsKey(new TupleKey(1,1))); // false!?
這是怎么回事? 在結構中使用可變對象(如數組)是否存在問題?
自定義struct
的默認相等和哈希代碼實現將基於其成員的默認相等和哈希代碼方法(在您的情況下為數組)。 該數組使用基於引用的身份,而不是基於值的身份。 如果要使具有相同值的不同數組相等,則需要重寫Equals
和GetHashCode
以依賴於數組的值。
通常,.NET中的類型會嘗試定義Equals
,以便如果x
和y
是類的私有字段,則除非該類寫入這些字段,否則x.Equals(y)
值無法更改。 如果x
和y
是可變引用類型,則意味着x.Equals(y)
可以為true的唯一方法是x
和y
標識同一對象。 如果x
和y
標識狀態恰好相同的不同對象時x.Equals(y)
返回true,並且在其他地方引用這些對象之一的代碼將修改其狀態,則外部代碼可以更改該值不能訪問x
或y
的x.Equals(y)
。
我認為可以合理地認為.NET缺乏“不變數組”類型。 如果存在這樣的類型,那么它們是不可變的,可以保證如果兩個實例包含相同的項目,它們將永遠這樣做。 但是,由於.NET沒有任何此類類型,因此必須忍受這種限制。
最好的辦法可能是讓您的結構的構造函數構造一個數組,該數組比傳入的數組長一個元素,並包含原始數組內容的副本以及其中值的哈希值。 這樣,該數組將永遠不會暴露給外部代碼,因此可以保證永遠不會被修改。 您的equals
方法可以檢查與您的類型進行比較的對象是否是相同類型的另一個結構,如果是,則檢查數組的長度是否相同,存儲的哈希值是否匹配,以及是否是否所有其他項匹配。 然后,您的GetHashCode
值應返回存儲在額外數組插槽中的哈希值。 如果這樣做,還應該實現IEquatable<yourOwnType>
。
請注意,雖然可以使用字段而不是數組插槽來保存哈希值,但是使用數組插槽會更有效,並且可以避免不正確的多線程代碼創建其哈希值的結構實例的可能性。與數組的內容不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.