C#等式检查

Yip*_*Yay 10 c# equality

你对写作平等检查的方法structsclasses创建?

1) "完全"平等检查是否需要多大的样板代码(如override Equals,override GetHashCode,通用Equals,operator==,operator!=)?

2)您是否明确指定您的类为IEquatable<T>接口建模?

3)我是否理解正确,没有实际的方法来自动应用Equals覆盖,当我调用类似的东西时a == b,我总是要实现Equalsoperator==成员?

Jon*_*eet 20

你是对的,这是很多样板代码,你需要单独实现所有东西.

我建议:

  • 如果您要实现值相等,则覆盖GetHashCodeEquals(object)- 为==创建重载并在IEquatable<T>不执行此操作的情况下实现可能会导致非常意外的行为
  • IEquatable<T>如果你压倒一切Equals(object),我会一直执行GetHashCode
  • 我只是很少重载==运算符
  • 正确地为未密封的类实现相等性是棘手的,并且仍然可以产生令人惊讶的/不期望的结果.如果层次结构中的类型需要相等,请实现IEqualityComparer<T>表达您感兴趣的比较.
  • 可变类型的平等通常是一个坏主意,因为两个对象可以相等然后不等...如果一个对象在被用作哈希表中的键之后被变异(以相等的方式),你赢了再也找不到了.
  • 一些锅炉板的结构略有不同......但像Marc一样,我很少编写自己的结构.

这是一个示例实现:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

是的,这是一个很多样板的问题,实现之间的变化很少:(

的实施==稍微比它可能是效率较低,因为它会通过打电话给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);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 6

我很少为课程做任何特别的事情; 对于大多数常规对象,引用平等工作正常.

我甚至更少写一个struct; 但由于结构代表价值,通常适当提供平等等.这通常涉及一切; 等于,==,!=和IEquatable<T>(因为这可以避免使用场景中的装箱EqualityComparer<T>.Default.

样板文件通常不会太成问题,但像resharper这样的IIRC工具可以在这里提供帮助.

是的,建议保持Equals和==同步,这需要明确地完成.