18

オブジェクトと NULL を比較する必要があります。オブジェクトが NULL でない場合、いくつかのデータを入力します。

コードは次のとおりです。

 if (region != null)
 {
  ....
 }

これは機能していますが、ループしてループすると、領域オブジェクトがnullではない場合があります(デバッグモードで内部のデータを確認できます)。デバッグ時のステップバイステップでは、IFステートメント内には入りません...次の式でクイックウォッチを実行すると、(region == null)がfalseを返し、AND(region != null ) false も返す...なぜ、どのように?

アップデート

オブジェクトが == および != オーバーロードされていることを誰かが指摘しています。

    public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }


    public static bool operator !=(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }
        return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id);
    }
4

8 に答える 8

29

== および/または != 演算子は、領域オブジェクトのクラスに対してオーバーロードされていますか?

オーバーロードのコードを投稿したので、次のようにします。

オーバーロードはおそらく次のようになるはずです (コードはJon SkeetPhilip Rieckによる投稿から抜粋):

public static bool operator ==(Region r1, Region r2)
{
    if (object.ReferenceEquals( r1, r2)) {
        // handles if both are null as well as object identity
        return true;
    }

    if ((object)r1 == null || (object)r2 == null)
    {
       return false;
    }        

    return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}

public static bool operator !=(Region r1, Region r2)
{
    return !(r1 == r2);
}
于 2008-09-30T22:51:49.570 に答える
16

これらの演算子のオーバーロードは壊れています。

まず、== を呼び出して結果を反転するだけで != が実装されていると、作業がずっと楽になります。

第二に、== で無効性をチェックする前に、次のようにする必要があります。

if (object.ReferenceEquals(r1, r2))
{
    return true;
}
于 2008-09-30T22:59:25.450 に答える
7

両方のオーバーロードが正しくありません

 public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

r1 と r2 が null の場合、r2 も null であっても、最初のテスト ( object.ReferenceEquals(r1, null) ) は false を返します。

試す

//ifs expanded a bit for readability
 public static bool operator ==(Region r1, Region r2)
    {
        if( (object)r1 == null && (object)r2 == null)
        {
           return true;
        }
        if( (object)r1 == null || (object)r2 == null)
        {
           return false;
        }        
        //btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }
于 2008-09-30T23:03:56.827 に答える
3

これは、複数のスレッドが同じデータを処理している場合に発生することがあります。このような場合は、ロックを使用して、それらが互いに干渉するのを防ぐことができます。

于 2008-09-30T22:50:52.180 に答える
2

型「T」の等値比較では、次のメソッドをオーバーロードします。

int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)

タイプ固有の比較コードは、タイプ セーフなIEquatable<T>インターフェイス メソッドという 1 つの場所で実行する必要がありますEquals(T other)。別の型 (T2) と比較する場合IEquatable<T2>も同様に実装し、その型のフィールド比較コードを Equals(T2 other) に入れます。

オーバーロードされたすべてのメソッドと演算子は、等値比較タスクをメインのタイプ セーフな Equals(T other) インスタンス メソッドに転送する必要があります。これにより、クリーンな依存関係階層が維持され、各レベルでより厳密な保証が導入されて冗長性と不要な複雑さが排除されます。

bool Equals(object other)
{
    if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
        return Equals( (T)other) ); //forward to IEquatable<T> implementation
    return false; //other is null or cannot be compared to this instance; therefore it is not equal
}

bool Equals(T other)
{
    if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return false;
    //if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
        //return true;
    return field1.Equals( other.field1 ) &&
           field2.Equals( other.field2 ); //compare type fields to determine equality
}

public static bool operator ==( T x, T y )
{
    if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return false; //x was null, y is not null
    return true; //both null
}

public static bool operator !=( T x, T y )
{
    if ((object)x != null)
        return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return true; //x was null, y is not null
    return false; //both null
}

討論:

前の実装では、型固有の (つまり、フィールドの等価性) 比較を、IEquatable<T>その型の実装の最後に集中させます。==and演算子は、並列では!=あるが反対の実装をしています。私は、依存するものに対して余分なメソッド呼び出しがあるように、一方が他方を参照するよりもこれを好みます。同等に機能するオペレーターを提供するのではなく、!=オペレーターが単純にオペレーターを呼び出す場合は、余分なメソッド呼び出しを使用して回避することもできます。1. 場合によっては不要なオーバーヘッドが発生したり、2. インスタンスがそれ自体と他のインスタンスと比較される頻度に応じて一貫性のないパフォーマンスが発生したりする可能性があるため、自己との比較は equals 演算子と実装から除外されています。==!(obj1 == obj2)IEquatable<T>

私が好まないが言及すべき別の方法は、この設定を逆にして、代わりに等値演算子に型固有の等値コードを集中させ、それに依存する Equals メソッドを持たせることです。次に、次のショートカットを使用できますReferenceEquals(obj1,obj2)Philip が以前の投稿で述べたように、参照の等価性と null の等価性を同時にチェックしますが、その考えは誤解を招くものです。1 つの石で 2 羽の鳥を殺しているように見えますが、実際にはより多くの作業を作成しています。オブジェクトが両方とも null でも同じインスタンスでもないことを確認した後、さらに、各インスタンスが無効です。私の実装では、1 つのインスタンスが null であることを 1 回だけチェックします。Equals インスタンス メソッドが呼び出されるまでに、比較される最初のオブジェクトが null である可能性は既に排除されているため、残りの作業は、もう一方が null であるかどうかを確認することだけです。そのため、最大 2 回の比較の後、使用する方法に関係なく、フィールド チェックに直接ジャンプします (Equals(object),Equals(T),==,!=)。また、前述したように、ほとんどの場合、実際にそれ自体を比較して反対している場合は、フィールド比較に入る直前に Equals メソッドにそのチェックを追加できます。最後に追加するポイントは、すべてのレベルで冗長/無用なチェックを導入することなく、フロー/依存関係の階層を維持できることです。

于 2009-04-09T19:55:26.273 に答える
0

監視しているパラメータの横にある更新アイコンをクリックする必要がある可能性もあります。VSは、すべてのステートメント/パラメーターを評価するのではなく、パフォーマンスに追いつくようにします。関連性のない場所に変更を加える前に、確認してください。

于 2008-10-01T18:50:32.357 に答える
0
bool comp;
if (object.IsNullOrEmpty(r1))
{
    comp = false;
}

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
于 2012-11-22T20:04:55.183 に答える
0

ここでのこれらのチェックが正しくないということですか。

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...
于 2008-09-30T22:59:27.213 に答える