我已经阅读了关于Dictionary.ContainsKey()
如何工作的MSDN文档,但我想知道它实际上是如何进行相等比较的?基本上,我有一个键入引用类型*的字典,我希望ContainsKey()
方法检查该引用类型的某个属性作为确定密钥是否存在的基础。例如,如果我有Dictionary(MyObject, int)
而MyObject
有一个名为“TypeID”的公共属性(int
),我是否可以ContainsKey(MyObject myObject)
检查是否有密钥的TypeID
等于myObject
?我可以重载==
运算符吗?
double Length
); “持续时间”是我的音乐节目中使用的基本类型,表示特定声音持续多长时间。我从中派生出类,其中包含更复杂的时序概念,如西方音乐时间签名,但希望所有这些都在长度方面具有可比性。编辑:正如所建议的那样,我在我的对象上实现了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
}
}
}
这就是我需要做的全部吗?
答案 0 :(得分:11)
编辑:这是您更新的示例的代码。注意:我觉得将字段公开为受保护有点奇怪,并且还有一个公开该成员的虚拟属性。根据此方案,某些内容可能会覆盖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;
}
}
有关Dictionary类使用的默认EqualityComparer.Default的信息,请参阅IEqualityComparer
。
如果您不想在课程上覆盖GetHashCode
和Equals
,或者您不能。有一个overload of the Dictionary constructor,您可以在其中提供要使用的特定IEqualityComparer
。
这是一个简单的实现界面,但您需要注意尊重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
}
}
使用它只是去
new Dictionary<MyObject, int>(new MyObjectEqualityComparer());
如果要使用默认的IEqualityComparer,则需要在MyObjectEqualityComparer上提供大致相同的方法。如果您实施IEquatable, 可以避免覆盖object.Equals()
。但是我强烈反对它,因为这样做会产生一些令人惊讶的行为。您最好覆盖Equals
,以便对所有对Equals的调用具有一致的行为,并且具有与Equals正确匹配的散列。我不得不修复由过去只实现IEquatable.
答案 1 :(得分:7)
内部Dictionary
使用EqualityComparer
。首先,它将检查密钥是否实现IEquatable
。如果key未实现此接口,则会调用Equals
方法。