C#平等检查 [英] C# equality checking
问题描述
的你对写作的平等将检查结构
和类
办法创建?
What's your approach on writing equality checks for the structs
and classes
you create?
1)是否完全平等检查需要多少样板code(比如重载equals
,覆盖GetHash code
,通用等于
,运算符==
,运算符!=
)?
1) Does the "full" equality checking require that much of boilerplate code (like override Equals
, override GetHashCode
, generic Equals
, operator==
, operator!=
)?
2)你明确指定你的类模型中的 IEquatable< T>
接口
2) Do you specify explicitly that your classes model the IEquatable<T>
interface?
3)我理解正确的话,那还有自动应用等于
覆盖没有实际的方式,当我调用类似 A == b
键,我总是要同时实现等于
和运算符==
成员?
3) Do I understand correctly, that there is no actual way to automatically apply Equals
overrides, when I invoke something like a == b
and I always have to implement both the Equals
and operator==
members?
推荐答案
您说的没错,这是很多样板code,而你需要分别实现一切。
You're right, this is a lot of boiler-plate code, and you need to implement everything separately.
我会建议:
- 如果你要实现值相等可言,覆盖
GetHash code
和等于(对象)
- 用于创建==过载和实施IEquatable&LT; T&GT;
没有做,可能会导致非常意外的行为 - 我会始终贯彻
IEquatable&LT; T&GT;
如果你重写等于(对象)
和GetHash code
- 我只重载==操作符更很少
- 非密封类正确实施平等是棘手的,而且还可以产生令人惊讶的/不希望的结果。如果你需要的类型平等的层次结构,实施
的IEqualityComparer&LT; T&GT;
前pressing你感兴趣的比较 - 平等可变类型通常是一个坏主意,因为两个对象可以相等,然后不等后来......如果一个对象突变(在影响平等路),它被用来作为哈希表中的键后,你将无法再次找到它。
- 部分锅炉板对于结构略有不同......但像马克,我很少写我自己的结构。
- If you're going to implement value equality at all, override
GetHashCode
andEquals(object)
- creating overloads for == and implementingIEquatable<T>
without doing that could result in very unexpected behaviour - I would always implement
IEquatable<T>
if you're overridingEquals(object)
andGetHashCode
- I only overload the == operator more rarely
- Implementing equality correctly for unsealed classes is tricky, and can still produce surprising/undesirable results. If you need equality for types in a hierarchy, implement
IEqualityComparer<T>
expressing the comparison you're interested in. - Equality for mutable types is usually a bad idea, as two objects can be equal and then unequal later... if an object is mutated (in an equality-affecting way) after it's been used as a key in a hash table, you won't be able to find it again.
- Some of the boiler-plate is slightly different for structs... but like Marc, I very rarely write my own structs.
下面是一个示例实现:
using System;
public sealed class Foo : IEquatable<Foo>
{
private readonly string name;
public string Name { get { return name; } }
private readonly int value;
public int Value { get { return value; } }
public Foo(string name, int value)
{
this.name = name;
this.value = value;
}
public override bool Equals(object other)
{
return Equals(other as Foo);
}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 31 + (name == null ? 0 : name.GetHashCode());
hash = hash * 31 + value;
return hash;
}
public bool Equals(Foo other)
{
if ((object) other == null)
{
return false;
}
return name == other.name && value == other.value;
}
public static bool operator ==(Foo left, Foo right)
{
return object.Equals(left, right);
}
public static bool operator !=(Foo left, Foo right)
{
return !(left == right);
}
}
是的,这是一个很大的样板赫克,其很少的实现之间变化:(
And yes, that's a heck of a lot of boilerplate, very little of which changes between implementations :(
的 ==
是略的效率低于它可能是,因为它会调用通过对等于实施(对象)
这需要做动态类型检查...但另一种方法是更锅炉板,像这样的:
The implementation of ==
is slightly less efficient than it might be, as it will call through to Equals(object)
which needs to do the dynamic type check... but the alternative is even more boiler-plate, like this:
public static bool operator ==(Foo left, Foo right)
{
if ((object) left == (object) right)
{
return true;
}
// "right" being null is covered in left.Equals(right)
if ((object) left == null)
{
return false;
}
return left.Equals(right);
}
这篇关于C#平等检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!