3

私は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");

「2 番目の比較は決して true を返しません」、そうです。つまり、D は B のサブクラスであるため、2 番目の比較では B から Equals メソッドが呼び出され、true が返されます。これは完全に理にかなっています。私は何かを逃していますか?

4

2 に答える 2

2

Bill は、オーバーライドさ Equals(object)れたメソッドがDで呼び出された場合、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))

したがって、実装に問題があると言っている本は正しいです。サンプルがそれを十分に示していないだけです。

于 2013-01-02T22:00:01.023 に答える
0

これは、as演算子と継承によるものです。

AB、およびBから派生した2 つのクラスがあるとします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
于 2013-01-02T22:00:11.710 に答える