[英]C# equality checking
What's your approach on writing equality checks for the structs
and classes
you create? 您为自己创建的
structs
和classes
编写相等性检查的方法是什么?
1) Does the "full" equality checking require that much of boilerplate code (like override Equals
, override GetHashCode
, generic Equals
, operator==
, operator!=
)? 1) “完全”等式检查是否需要大量样板代码(如
override Equals
, override GetHashCode
,泛型Equals
, operator==
, operator!=
)?
2) Do you specify explicitly that your classes model the IEquatable<T>
interface? 2)您是否明确指定您的类为
IEquatable<T>
接口建模?
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? 3)我是否理解正确,没有实际的方法来自动应用
Equals
覆盖,当我调用类似a == b
东西时,我总是要实现Equals
和operator==
成员?
You're right, this is a lot of boiler-plate code, and you need to implement everything separately. 你是对的,这是很多样板代码,你需要单独实现所有东西。
I would recommend: 我建议:
GetHashCode
and Equals(object)
- creating overloads for == and implementing IEquatable<T>
without doing that could result in very unexpected behaviour GetHashCode
和Equals(object)
- 为==创建重载并实现IEquatable<T>
而不这样做可能会导致非常意外的行为 IEquatable<T>
if you're overriding Equals(object)
and GetHashCode
Equals(object)
和GetHashCode
我总是会实现IEquatable<T>
IEqualityComparer<T>
expressing the comparison you're interested in. IEqualityComparer<T>
。 Here's a sample implementation: 这是一个示例实现:
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: ==
的实现效率稍差 ,因为它会调用Equals(object)
,它需要进行动态类型检查......但替代方案更像是样板,如下所示:
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);
}
I rarely do anything special for classes; 我很少为课程做任何特别的事情; for most regular objects referential equality works fine.
对于大多数常规对象,引用平等工作正常。
I even more rarely write a struct
; 我甚至更少写一个
struct
; but since structs represent values it is usually appropriate to provide equality etc. This would usually involve everything; 但由于结构代表价值 ,通常适当提供平等等。这通常涉及一切; Equals, ==, != and
IEquatable<T>
(since this avoids boxing in scenarios using EqualityComparer<T>.Default
. Equals,==,!=和
IEquatable<T>
(因为这可以避免在使用EqualityComparer<T>.Default
场景中进行装箱。
The boilerplate isn't usually too problematic, but IIRC tools like resharper can help here. 样板文件通常不会太成问题,但像resharper这样的IIRC工具可以在这里提供帮助。
Yes, it is advisable to keep Equals and == in sync, and this needs to be done explicitely. 是的,建议保持Equals和==同步,这需要明确地完成。
You just need to implement operator== for a==b . 你只需要为== b实现operator ==。
As I like my data in dictionaries sometimes I override GetHashCode. 由于我喜欢字典中的数据,有时候我会覆盖GetHashCode。
Next I implement Equals (as an unmentioned standard ... this is because there is no constraint for equality when using generics) and specify implementing IEquatable. 接下来我实现Equals(作为一个未提及的标准......这是因为在使用泛型时没有相等的约束)并指定实现IEquatable。 Since I am going to do this I might as well point my == and != implementations to Equals.
由于我要这样做,我不妨将我的==和!=实现指向Equals。 :)
:)
See What is "Best Practice" For Comparing Two Instances of a Reference Type? 请参阅比较参考类型的两个实例的“最佳实践”是什么?
You can avoid boiler plate code (hope C#/VS team brings something easy for developers in their next iteration) with the help of a snippet, here is one such.. 您可以在一个片段的帮助下避免样板代码(希望C#/ VS团队在下一次迭代中为开发人员带来一些简单的东西), 这里有一个这样的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.