![](/img/trans.png)
[英]Dictionary.ContainsKey return false even thought the key exists
[英]Dictionary.ContainsKey return False, but a want True
namespace Dic
{
public class Key
{
string name;
public Key(string n) { name = n; }
}
class Program
{
static string Test()
{
Key a = new Key("A");
Key b = new Key("A");
System.Collections.Generic.Dictionary<Key, int> d = new System.Collections.Generic.Dictionary<Key, int>();
d.Add(a, 1);
return d.ContainsKey(b).ToString();
}
static void Main(string[] args)
{
System.Console.WriteLine(Test());
}
}
}
我應該改變什么才能成真?
你想要真實 - 但a和b是不同的對象。
您需要在類Key上覆蓋GetHashCode和Equals
public class Key
{
string name;
public Key(string n) { name = n; }
public override int GetHashCode()
{
if (name == null) return 0;
return name.GetHashCode();
}
public override bool Equals(object obj)
{
Key other = obj as key;
return other != null && other.name == this.name;
}
}
如果你重寫Key.GetHashCode和Key.Equals,它可能會有所幫助。
在Key
:
public override bool Equals(object obj)
{
var k = obj as Key;
if (k != null)
{
return this.name == k.name;
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return this.name.GetHashCode();
}
如果你沒有能夠像其他人提到的那樣覆蓋相等的運算符/ Equals / GetHashCode(如你所知,你不控制對象的源代碼),你可以在字典的構造函數中提供IEqualityComparer<Key>
實現執行你的平等檢查。
class KeyComparer : IEqualityComparer<Key>
{
public bool Equals(Key x, Key y)
{
return x.Name == y.Name;
}
public int GetHashCode(Key obj)
{
return obj.Name.GetHashCode();
}
}
就目前而言,您的Key是一個引用對象,因此除非您告訴世界(或字典),否則僅在引用時確定相等性。
覆蓋類的GetHashCode和Equals方法以使其在字典中正常工作並不是一個非常好的方法。 字典的行為方式應該是字典的實現細節,而不是用作鍵的任何類。 當你想在具有不同行為的不同詞典中使用該類時,你會遇到麻煩。 或者,如果您無權訪問類源代碼。
一個更好的鼠標陷阱是給字典自己的比較器。 例如:
using System;
using System.Collections.Generic;
class Program {
static void Main(string[] args) {
var d = new Dictionary<Key, int>(new MyComparer());
d.Add(new Key("A"), 1);
Console.WriteLine(d.ContainsKey(new Key("a")));
Console.ReadLine();
}
private class MyComparer : IEqualityComparer<Key> {
public bool Equals(Key x, Key y) {
return string.Compare(x.Name, y.Name, true) == 0;
}
public int GetHashCode(Key obj) {
return obj.Name.ToUpper().GetHashCode();
}
}
public class Key {
public string Name { get; set; }
public Key(string name) { Name = name; }
}
}
要將您自己的類用作字典鍵,您應該重寫GetHashCode和Equals。 否則,它將使用內存地址來檢查是否相等。
public class Key { string name; public Key(string n) { name = n; } public override int GetHashCode() { return name.GetHashCode(); } public override bool Equals(object obj) { var other = obj as Key; if( other == null ) return false; return name == other.name; } }
你的問題是
new Key("A").Equals(new Key("A"))==false.
和
new Key("A").GetHashCode()!=new Key("A").GetHashCode()
解決這個問題,我覺得應該可行。 要修復它,請覆蓋Equals方法並檢查名稱值是否相同。 如果要覆蓋Equals,還應覆蓋GetHashCode。
您需要覆蓋Key類的Equals和GetHashCode方法。
它們內部具有相同的值但是!= b,因為它們是2個不同的變量。
您需要覆蓋Key類的Equals
和GetHashCode
方法。 在您的情況下,您可以根據鍵的名稱進行比較(如果您的類更復雜,則可以在任何其他唯一屬性上進行比較)。
public class Key {
string name;
public Key(string n) { name = n; }
public override bool Equals(object obj) {
Key k = obj as Key;
if (k == null)
return false;
return name.Equals(k.name);
}
public override int GetHashCode() {
return name.GetHashCode();
}
}
1.覆蓋等於,獲取哈希代碼和'=='運算符。
Key類必須重寫Equals
,以便Dictionary檢測它們是否相同。 默認實現僅檢查引用。
這里:
public bool Equals(Key other)
{
return this == other;
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Key))
{
return false;
}
return this.Equals((Key)obj);
}
public static bool operator ==(Key k1, Key k2)
{
if (object.ReferenceEquals(k1, k2))
{
return true;
}
if ((object)k1 == null || (object)k2 == null)
{
return false;
}
return k1.name == k2.name;
}
public static bool operator !=(Key k1, Key k2)
{
if (object.ReferenceEquals(k1, k2))
{
return false;
}
if ((object)k1 == null || (object)k2 == null)
{
return true;
}
return k1.name != k2.name;
}
public override int GetHashCode()
{
return this.name == null ? 0 : this.name.GetHashCode();
}
2.如果可能,請使用結構。
您應該使用這樣的不可變數據類型的結構,因為它們是按值傳遞的。 這意味着你不會意外地將兩個不同的值混合到同一個鍵中。
然后,您需要在Key類上重寫GetHashCode和Equals。
如果不這樣做,您將獲得兩者的默認實現。 這導致a和b的哈希碼很可能不一樣(我不知道默認實現是怎么樣的),而a肯定不等於b(默認的Equals()實現檢查引用相等)。
在您的情況下,假設“name”不是null,它可以實現為
public class Key
{
string name;
public override int GetHashCode()
{
return name.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
Key objAsKey = obj as Key;
if (objAsKey == null)
{
return false;
}
return this.name.Equals(objAsKey.Name);
}
}
這是否是一個令人滿意的哈希是一個不同的故事,但它顯示了原則。
在這種情況下,ContainsKey將Key作為對象進行比較,並檢查對象本身是否相同 - 它們不是。 你需要實現IComparable或覆蓋Key.Equals或類似的東西,以使它做你想要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.