2

Point2クラスがあり、次のEqualsを実装したいとします。

public override bool Equals ( object obj )

public bool Equals ( Point2 obj )

これは、Effective C#3の本からのものです。

public override bool Equals ( object obj )
{
    // STEP 1: Check for null
    if ( obj == null )
    {
        return false;
    }

    // STEP 3: equivalent data types
    if ( this.GetType ( ) != obj.GetType ( ) )
    {
        return false;
    }
    return Equals ( ( Point2 ) obj );
}

public bool Equals ( Point2 obj )
{
    // STEP 1: Check for null if nullable (e.g., a reference type)
    if ( obj == null )
    {
        return false;
    }
    // STEP 2: Check for ReferenceEquals if this is a reference type
    if ( ReferenceEquals ( this, obj ) )
    {
        return true;
    }
    // STEP 4: Possibly check for equivalent hash codes
    if ( this.GetHashCode ( ) != obj.GetHashCode ( ) )
    {
        return false;
    }
    // STEP 5: Check base.Equals if base overrides Equals()
    System.Diagnostics.Debug.Assert (
        base.GetType ( ) != typeof ( object ) );

    if ( !base.Equals ( obj ) )
    {
        return false;
    }

    // STEP 6: Compare identifying fields for equality.
    return ( ( this.X.Equals ( obj.X ) ) && ( this.Y.Equals ( obj.Y ) ) );
}

それはやり過ぎですか?

4

4 に答える 4

3

継承階層で平等をサポートするのは難しいです。あなたはあなたが何を意味するのかを正確に理解する必要があります。ここで本当に継承が必要ですか?そうでない場合-Point2がSystem.Objectから直接派生し、それを封印することができれば、作業は少し楽になります。その場合、私は以下を使用します:

public override bool Equals (object obj)
{
    return Equals(obj as Point2);
}

public bool Equals (Point2 obj)
{
    // STEP 1: Check for null if nullable (e.g., a reference type)
    // Note use of ReferenceEquals in case you overload ==.
    if (object.ReferenceEquals(obj, null))
    {
        return false;
    }

    // STEP 2: Check for ReferenceEquals if this is a reference type
    // Skip this or not? With only two fields to check, it's probably
    // not worth it. If the later checks are costly, it could be.
    if (object.ReferenceEquals( this, obj))
    {
        return true;
    }

    // STEP 4: Possibly check for equivalent hash codes
    // Skipped in this case: would be *less* efficient

    // STEP 5: Check base.Equals if base overrides Equals()
    // Skipped in this case

    // STEP 6: Compare identifying fields for equality.
    // In this case I'm using == instead of Equals for brevity
    // - assuming X and Y are of a type which overloads ==.
    return this.X == obj.X && this.Y == obj.Y;
}
于 2009-02-20T17:45:27.733 に答える
2

実際にはそうではありません-あなたはほとんどすべての可能性を説明しています。このコードがスクラッチアプリケーション以外のものである場合は、奇妙なオブジェクトの同等性の動作による論理エラーをデバッグするのが面倒なので、このアプローチの利点を検討する必要があります。

于 2009-02-20T17:45:03.053 に答える
1

私にはあなたが望むものとまったく同じように見えます。そのブロック全体は、要約すると次のようになります。

「まったく同じインスタンスの場合はtrueを返します。同じX値とY値を持つ別々のインスタンスの場合はtrueを返します。他のすべての場合(null、異なるタイプ、異なるx / y値)はfalseを返します。」

于 2009-02-20T17:44:44.070 に答える
1

確かに、equalsメソッド用に記述したいコードよりも多くのコードがあります。ReferenceEqualsやHashCodesのチェックなど、冗長なチェックがたくさんあります(関数の最後の行で構造が等しいかどうかをチェックするため、これらのチェックは冗長です)。シンプルで読みやすいコードに焦点を当てます。

public bool Equals(object o)
{
    Point2 p = o as Point2;
    if (o != null)
        return this.X == o.X && this.Y == o.Y;
    else
        return false;
}

equalsメソッドは構造的等式を使用するため、フィールドに基づく実装でGetHashCodeをオーバーライドするようにしてください。

于 2009-02-20T17:45:20.683 に答える