2012-02-16 34 views
3

私はC#の文字列クラスの比較演算子のために実装されたコードを調べようとしました。何見つかったことは、このでした:私はそれが私にトリックを再生しているリフレクターであるかどうかわからないが、私は自分のクラスのために、この戦略を実行しようとしたとき、私は対等の間で無限ループを持っ文字列等価演算子== in c#

//THIS IS NOT WHAT I MEANT 
public static bool Equals(object objA, object objB) 
{ 
    return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB))); 
} 

//THIS IS WHAT I SEE REALLY and the above is what I would expect to see 
public static bool Equals(string a, string b) 
{ 
    return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b))); 
} 



public static bool operator ==(string a, string b) 
{ 
    return Equals(a, b); 
} 

とオーバーロードされた==演算子(期待通り)。文字列クラスで異なるがSTHであるか、それはStringクラスの一部であることが、Objectクラスに

static Equals(object o1, object o2) 

方法を報告している私のリフレクターのですか?

+0

==演算子を使用していませんか?インスタンスメソッドなので、静的なEqualsメソッドと同じにすることはできません。あなたが提供したコードに基づいて、私は無限ループを見ません。インスタンスEqualsメソッドを表示できますか? – ken

+0

申し訳ありませんが、私はこの質問を更新しました。間違った定義を投稿しました... – Bober02

+1

私のopnionの無限は、(a == b)がEquals(文字列a、文字列b)で呼び出されたときに発生します。 STATIC型のaとbは文字列なので、オーバーロードされた演算子==が呼び出されます。私の簡単な例でこれをチェックし、ここにsthがあるかどうかわかりません。 – Bober02

答えて

6

C#の等価演算子は多型ではありません。 objA == objBを評価すると、objAおよびobjB変数の宣言された型がstringではなく、==(string a, string b)ではなく、演算子の実装(参照の一致をチェックする)が実際に実行されます。

コードでエラーが発生している可能性があります。objectにクラスインスタンスをキャストしていないため、==演算子が評価されていません。

あなたが持っていると仮定:

public static bool Equals(MyClass objA, MyClass objB) 
{ 
    return object.ReferenceEquals(objA, objB) || objA != null && objB != null && objA.Equals(objB); 
} 

更新:に相当する...

public static bool Equals(MyClass objA, MyClass objB) 
{ 
    return (object)objA == (object)objB || objA != null && objB != null && objA.Equals(objB); 
} 

public static bool Equals(MyClass objA, MyClass objB) 
{ 
    return objA == objB || objA != null && objB != null && objA.Equals(objB); 
} 

...あなたがそれを交換する必要がありますStringクラスにはbotが含まれていますha static bool Equals(string a, string b)方法およびa static bool Equals(object a, object b)方法。相違点は、前者がStringクラス内で定義され、後者がObjectクラス(Stringの基本クラス)から継承される点です。リフレクターは、設定に基づいて継承されたメソッドを表示する場合と表示しない場合があります。あなたの投稿をコードで

objAobjBの宣言された型が、その後objectパラメータを持つオペレータは関係なく、インスタンスの実際のタイプの、と呼ばれるになるだろう、objectからです。

更新:あなたの更新されたコードは、無限再帰が含まれているように見えるん。私はそれがリフレクターツール内のバグかもしれないと考えています。

更新:これは、disassemberのバグのようです。 Equals(string a, string b)演算子の実装における最初の条件は、逆アセンブルされたC#コードでa == bと表示されます。しかし、ILコードの最初の数行は、実際には次のとおり

ldarg.0 
ldarg.1 
bne.un.s IL_0006 

ldc.i4.1 
ret 

bne.un.sが指定された2つの符号なし整数値が等しい(符号なしの値)でない場合、オフセット短縮形でターゲット命令への分岐」と定義されます。

このように、参照の平等が結局実行されているように見えます。

+0

これはケースです!しかし、私の反射階級にはそれがありません... – Bober02

+0

私は今本当に混乱しています。おそらく次のコードが実行されます: – Bober02

+0

string a = "aaaa"; 文字列b = "bbbb"; – Bober02

7

String.Equals(object, object)メソッドはありません。
あなたはObject.Equalsが表示されています。

理由が再発しないのは、objA == objBが、カスタム文字列等価演算子ではなく、組み込みオブジェクト等価演算子を呼び出すことです。
(オペレーターの過負荷は、オペランドのコンパイル時タイプに基づいて解決されている)

+0

ある意味では、 'String.Equals(object、object)'メソッドがあります。それは 'String'クラス内で定義されておらず、' Object'クラスから継承されています。 – Douglas

+0

はい、私は文字列のパラメータ型を持っています。オーバーロードされた==演算子をもう一度呼び出すと、これはEqualsメソッドを再度呼び出すなどします。 – Bober02

+0

@Douglas静的メソッドは継承されません。あなたは 'String.Equals(object、object)'を呼び出すことはできません。静的な 'Object.Equals(object、object)'メソッドは文字列クラスのスコープ*内にあるので、 'Object.'パーツなしで呼び出すことができますが、継承されません。 – phoog

0

ザは、このされた意味の方法に等しい:

public static bool Equals(string a, string b) 
{ 
    /* == is the object equals- not the string equals */ 
    return a == b || (a != null && b != null && string.EqualsHelper(a, b)); 
} 

public static bool operator ==(string a, string b) 
{ 
    return string.Equals(a, b); 
} 

すなわち2つの文字列ではなく2つのオブジェクトをとるequalsメソッド

1

少ない混乱ソリューション:リフレクターはobjA.Equals方法について言うん何

public static bool Equals(MyClass a, MyClass b) 
{ 
    return ReferenceEquals(a, b) 
     || ((!ReferenceEquals(a, null) && !ReferenceEquals(b, null)) && a.Equals(b))); 
} 
関連する問題