[英]Dictionary.ContainsKey() - How does it work?
I've read the MSDN documentation on how Dictionary.ContainsKey()
works, but I was wondering how it actually makes the equality comparison? 我已经阅读了关于
Dictionary.ContainsKey()
如何工作的MSDN文档,但我想知道它是如何实际进行相等比较的? Basically, I have a dictionary keyed to a reference type* and I want the ContainsKey()
method to check a certain property of that reference type as its basis for determining if the key exists or not. 基本上,我有一个键入引用类型*的字典,我希望
ContainsKey()
方法检查该引用类型的某个属性作为确定密钥是否存在的基础。 For example, if I had a Dictionary(MyObject, int)
and MyObject
has a public property (of int
) called "TypeID", could I get ContainsKey(MyObject myObject)
to check to see if one of the keys has a TypeID
that is equal to myObject
? 例如,如果我有一个
Dictionary(MyObject, int)
并且MyObject
有一个名为“TypeID”的公共属性( int
),我可以获取ContainsKey(MyObject myObject)
来检查其中一个键是否具有TypeID
等于myObject
? Could I just overload the ==
operator? 我可以重载
==
运算符吗?
double Length
); double Length
); "Duration" is a base type used in my music program to denote how long a particular sound lasts. EDIT: As suggested, I implemented IEquitable on my object like so: 编辑:正如所建议的,我在我的对象上实现了IEquitable,如下所示:
public class Duration : IEquatable<Duration>
{
protected double _length;
/// <summary>
/// Gets or Sets the duration in Miliseconds.
/// </summary>
public virtual double Length
{
get
{
return _length;
}
set
{
_length = value;
}
}
// removed all the other code that as it was irrelevant
public override bool Equals(object obj)
{
Duration otherDuration = (Duration)obj;
if (otherDuration._length == _length)
{
return true;
}
else
{
return false
}
}
}
Is this all I need to do? 这就是我需要做的吗?
EDIT: here is code for your updated example. 编辑:这是您更新的示例的代码。 Note: I find it a little odd that you expose the field as protected, and also have a virtual property that exposes the member.
注意:我觉得将字段公开为受保护有点奇怪,并且还有一个公开该成员的虚拟属性。 Under this scheme something could override
Length
resulting in equality that looks at _lenght
to not behave as expected. 在这种方案下,有些东西可以覆盖
Length
导致相等,看起来_lenght
不按预期行事。
public class Duration : IEquatable<Duration>
{
protected double _length;
/// <summary>
/// Gets or Sets the duration in Miliseconds.
/// </summary>
public virtual double Length
{
get { return _length; }
set { _length = value; }
}
// removed all the other code that as it was irrelevant
public bool Equals(Duration other)
{
// First two lines are just optimizations
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _length.Equals(other._length);
}
public override bool Equals(object obj)
{
// Again just optimization
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
// Actually check the type, should not throw exception from Equals override
if (obj.GetType() != this.GetType()) return false;
// Call the implementation from IEquatable
return Equals((Duration) obj);
}
public override int GetHashCode()
{
// Constant because equals tests mutable member.
// This will give poor hash performance, but will prevent bugs.
return 0;
}
}
See EqualityComparer.Default for information on the default IEqualityComparer
used by the Dictionary class. 有关Dictionary类使用的默认
IEqualityComparer
信息,请参见EqualityComparer.Default 。
If you do not want to generally override GetHashCode
and Equals
on the class, or if you are unable to. 如果您不希望通常在类上覆盖
GetHashCode
和Equals
,或者您不能。 There is an overload of the Dictionary constructor in which you can provide the specific IEqualityComparer
to use. Dictionary构造函数有一个重载 ,您可以在其中提供要使用的特定
IEqualityComparer
。
It is a simple interface to implement, but you do need to be careful that you respect the contract for GetHashCode
or you can end up with unexpected behavior. 它是一个简单的实现接口,但您需要注意尊重
GetHashCode
的合同,否则最终会出现意外行为。
public class MyObjectEqualityComparer : IEqualityComparer<MyObject>
{
public bool Equals(MyObject x, MyObject y)
{
return x.TypeID == y.TypeID;
}
public int GetHashCode(MyObject obj)
{
return obj.TypeID; //Already an int
}
}
to use it just go 使用它只是去
new Dictionary<MyObject, int>(new MyObjectEqualityComparer());
If you want to use the default IEqualityComparer you need to provide roughly the same methods on MyObjectEqualityComparer. 如果要使用默认的IEqualityComparer,则需要在MyObjectEqualityComparer上提供大致相同的方法。 You can avoid overriding
object.Equals()
if you implement IEquatable . 如果实现IEquatable, 则可以避免覆盖object.Equals
object.Equals()
。 However I would strongly discourage it because doing so can create some surprising behavior. 但是我强烈反对它,因为这样做会产生一些令人惊讶的行为。 You are better of overriding
Equals
so that you have consistent behavior for all calls to Equals and have hashing that properly matches Equals. 您最好覆盖
Equals
以便对所有对Equals的调用具有一致的行为,并且具有与Equals正确匹配的散列。 I have had to fix a bug in inherited code caused by a past developer only implementing IEquatable.
我不得不修复由过去的开发人员实现
IEquatable.
导致的继承代码中的错误IEquatable.
Internally Dictionary
uses EqualityComparer
. 内部
Dictionary
使用EqualityComparer
。 Firstly it will check whether key implements IEquatable
. 首先,它将检查密钥是否实现
IEquatable
。 If key doesn't implement this interface, it will call Equals
method. 如果key未实现此接口,则将调用
Equals
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.