可以将字典中的第一个类型作为引用类型吗? 如果有,那是什么意思呢?
using System.Collections.Generic;
...
Dictionary<T1, T2> myDict = new Dictionary<T1, T2>();
据我了解,第一种类型 - 是关键。而且比 int 或 string 类型更频繁。
答案 0 :(得分:4)
可以使用引用类型作为字典中的键。要记住的重要一点是,引用类型使用引用相等作为默认值。
如果希望密钥类型的多个实例表示相同的值,则需要确保引用类型使用值相等。例如,string
是一种已经支持值相等的引用类型,因此使用字符串作为密钥是安全且容易的。
问题:
以下引用类型未实现值相等:
class Foo
{
public int X { get; set; }
}
因此,如果您创建两个实例,保持相同的值,则认为它们不相等:
var a = new Foo { X = 1 };
var b = new Foo { X = 1 };
Console.WriteLine(a == b); // false
Console.WriteLine(a.Equals(b)); // false
如果您使用a
作为键将值存储在字典中,则无法使用b
检索它:
var dict = new Dictionary<Foo, int>();
dict[a] = 10;
Console.WriteLine(dict[b]); // Key not found exception
<强>解决方案
要解决此问题,您可以(I)为您的类型实现值相等,或者(II)覆盖字典比较键的方式:
选项I:实现价值平等:
因此,如果您确实希望为引用类型实现值相等,那么您应该遵循these guidelines,这将为您提供类似的内容(不要忘记GetHashCode
):
class Foo2 : IEquatable<Foo2>
{
public int X { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as Foo2);
}
public bool Equals(Foo2 other)
{
if (Object.ReferenceEquals(other, null))
{
return false;
}
// Optimization for a common success case.
if (Object.ReferenceEquals(this, other))
{
return true;
}
if (this.GetType() != other.GetType())
return false;
return (X == other.X);
}
public override int GetHashCode()
{
return this.X;
}
public static bool operator ==(Foo2 lhs, Foo2 rhs)
{
if (Object.ReferenceEquals(lhs, null))
{
if (Object.ReferenceEquals(rhs, null))
{
return true;
}
return false;
}
return lhs.Equals(rhs);
}
public static bool operator !=(Foo2 lhs, Foo2 rhs)
{
return !(lhs == rhs);
}
}
现在,两个代表相同值的Foo2
实例被视为相等:
var c = new Foo2 { X = 1 };
var d = new Foo2 { X = 1 };
Console.WriteLine(c == d); // true
Console.WriteLine(c.Equals(d)); // true
如果您使用c
作为键将值存储在词典中, 将能够使用d
检索它:
var dict = new Dictionary<Foo2, int>();
dict[c] = 10;
Console.WriteLine(dict[d]); // 10
选项II:使用自定义相等比较器:
如果您不打算通常比较Foo
的实例,但仍希望能够在字典中比较它们时使用值相等,则可以提供自定义相等比较器作为实现完整值的替代方法平等:
class FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
// Doesn't handle null arguments!
return x.X == y.X;
}
public int GetHashCode(Foo obj)
{
return obj.X;
}
}
a
和b
仍被视为不相等,但现在您可以使用a
在字典中存储值,并使用b
检索它:
var dict = new Dictionary<Foo, int>(new FooComparer());
dict[a] = 10;
Console.WriteLine(dict[b]); // 10
答案 1 :(得分:2)
.NET框架中的每个对象都有GetHashCode
和Equals
方法。这些都是在字典中用作密钥所需要的。
默认引用类型使用引用相等性(即内存中相同对象的键),但您可以覆盖GetHashCode
和Equals
以提供您喜欢的任何相等语义。