【问题标题】:effective c# second edition errata [closed]有效的c#第二版勘误表[关闭]
【发布时间】:2013-01-02 21:55:02
【问题描述】:

我正在从 java 迁移到 c#。我正在阅读 Bill Wagner 的书,Effective C# second edition。我目前在第 1 章的第 6 项“了解许多不同的相等概念之间的关系”,其中第 40-41-42 页中有一个示例代码,它应该显示不正确地实现 Equals 会导致错误,我的错误我无法重现,它看起来像示例中的错误。这是下面的代码

public class B : IEquatable<D>
{
    public override bool Equals(object right)
    {
        //
        if (object.ReferenceEquals(right, null))
            return false;
        // Check reference equality:
        if (object.ReferenceEquals(this, right))
            return true;
        // Problems here, discussed below.
        B rightAsB = right as B;
        if (rightAsB == null)
            return false;
        return this.Equals(rightAsB);
    }

    #region IEquatable<B> Members
    public bool Equals(B other)
    {
        // elided
        return true;
    }
    #endregion
}

以及从 B 继承的 D 类

public class D : B,IEquatable<D>
{
    // etc.
    public override bool Equals(object right)
    {
        // check null:
        if (object.ReferenceEquals(right, null))
            return false;
        if (object.ReferenceEquals(this, right))
            return true;
        // Problems here.
        D rightAsD = right as D;

        if (rightAsD == null)
            return false;
        if (base.Equals(rightAsD) == false)
            return false;
        return this.Equals(rightAsD);
    }

    #region IEquatable<D> Members
    public bool Equals(D other)
    {
        // elided.
        return true; // or false, based on test
    }
    #endregion
}

根据书本,如下代码

        B baseObject = new B();
        D derivedObject = new D();
        // Comparison 1.
        if (baseObject.Equals(derivedObject))
            Console.WriteLine("Equals");
        else
            Console.WriteLine("Not Equal");
        // Comparison 2.
        if (derivedObject.Equals(baseObject))
            Console.WriteLine("Equals");
        else
            Console.WriteLine("Not Equal");

“第二次比较永远不会返回真”,它确实如此。我的意思是因为 D 是 B 的子类,所以第二个比较最终会从 B 调用 Equals 方法,该方法返回 true,这对我来说完全有意义。我错过了什么吗?

【问题讨论】:

  • 您发布的代码示例无法编译。
  • 对不起你是对的,错误在B类的定义中,它应该实现接口IEquatable而不是IEquatable

标签: c# errata


【解决方案1】:

我怀疑比尔的意思是,如果D 中的覆盖 Equals(object) 方法用baseObject 调用,由于这部分原因,它将返回false:

D rightAsD = right as D;

if (rightAsD == null)
    return false;

鉴于baseObject 的值不是D 实例的引用,rightAsD 应该是null,所以它会返回false

为了证明这一点,只需将baseObjectderivedObject 变量 的类型更改为object。 (不要更改它们初始化的值,只更改声明的类型。)或者,只需转换为 object

if (derivedObject.Equals((object) baseObject))

所以这本书说实施存在问题是正确的——只是示例没有完全展示它。

【讨论】:

  • 开门见山!谢谢
【解决方案2】:

这是由于as 运算符和继承。

假设您有 2 个类,AB,而 B 派生自 A

A a = new A();
B b = new B();

A x = b as A; // x is b
B y = a as B; // y is null

【讨论】:

  • derivedObject.Equals(baseObject) 将调用B.Equals(B) - 返回true。这就是问题所在。
  • 它应该调用Bpublic override bool Equals(object right),不是更具体的吗?哪个会导致as 语句失败?
  • 您的意思是演示问题吗?是的。
  • 是的,我只是想解释它是如何失败的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 2020-02-16
  • 2010-09-23
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多