2012-09-17 14 views
26

私は次のように彼のヌルチェックを書くのファンだ同僚を持っている:"ReferenceEquals(myObject、null)"は "myObject == null"よりも優れていますか?

if (!ReferenceEquals(myObject, null)) 

私が、一方で、読み、好むために、この構文は扱いにくい見つける:

if (myObject != null) 

私はオペレータのオーバーロードに関してReferenceEqualsのメリットについて議論するいくつかの記事やスタックオーバーフローに関する質問がありましたが、オペレータのオーバーロードシナリオの外側では、ReferenceEquals vs ==に何らかの利点がありますか?

+2

あなたの友人のバージョンがチェックは、互換性があり、問題がなる(読みにくくていることは注目に値すると同等だ、それら通常は)。 – keyser

+0

また、上記よりも悪いですが、 'if(!Object.ReferenceEquals(myObject、null)) 'と打つ必要があります。 –

+1

@ReedCopseyメソッドは、(直接的または間接的な)基本クラス 'System.Object'から静的な' ReferenceEquals'メソッドを継承するクラスまたは構造体の内部にあるため、入力する必要はありません。だから上のように書くことはOKです( 'new'メソッドを使って継承したメソッドを隠すことはもちろん可能ですが、それは悪い例外です)。 –

答えて

27

しかし、演算子のオーバーロードシナリオの外には、ReferenceEquals vs ==に何らかの利点がありますか?

ない

ん - 唯一の利点(と私はそれが利点の多くはないと主張したい)明示的Object.ReferenceEqualsを使用することは、それが過負荷にオペレータが等しく使用することは決してありませんということでしょう。オーバーロードされていない場合、== Operatorは、 "string以外のすべての参照型"に対して "その2つのオペランドが同じオブジェクトを参照する場合はtrueを返す"と定義されています。そのように、その等価物(過負荷ではない)を提供する。

私は、個人的にも、第2の構文を使用して、ヌルチェックのためによりメンテナンス可能なものを探しています。私はまた、operator==のオーバーロードは、nullに対して適切なチェックを提供しなければならないと主張しています。何らかの理由で(奇妙なことに)それがなかった場合は、その決定の背後にある特定の根拠がありますReferenceEqualsではなく、過負荷を使用したいと考えています。

3

誰かが==や!=演算子をオーバーライドしていれば、彼らは彼らが望むようにすることができます。たとえそれがreturn true;return false;のような本当の意味を持つことさえできます。さらに、オーバーロードされたオペレータがある場合は、それが実行されないような適切な機会がReferenceEquals(保証されておらず、おそらく十分ではありませんが、それでもなおです)です。

これは、オーバーロードされた演算子の任意の分かりやすい実装では、これはまったく問題になることはまずありません。私は個人的に==演算子をそのタイプまたはその特定のインスタンスに使用しないと魅力的な理由がない限り、ReferenceEqualsを使用しません。

+5

オーバーロードされた '=='演算子が不十分/不適切に実装されている場合、*それは修正されるべきバグです。 'ReferenceEquals()'を使ってそれを回避するのは適切な方法ではありません。 –

+3

@MichaelBurrあなたはあなたがそのタイプを支配していると仮定しているので、それを修正する能力があります。それは常にそうではありません。 – Servy

1

ヌルチェックでは、2人は常に同じ結果を返す必要があります。 ReferenceEqualsか==演算子が使用されていたかどうかにかかわらず、null以外の参照がnullに等しい場合(nullオブジェクトパターンを使用している場合でも)、が非常にです。ですから、そのシナリオでは、== /!=を使用します。

私は==演算子をオーバーロードされた場合は、も参照を使用してわずか速いかもしれない、と言うでしょう。オーバーロードされた演算子の場合は、呼び出しスタック上に余分なフレームがあります。 ReferenceEqualsを使用すると、チェックのみが実行されることが保証されます。

他のほとんどのシナリオでは、通常は== /!=も使用します。全体のアイデアは、オペレータが「平等」を定義することです。 (実際には、ほとんどの複合オブジェクトは構造的に同等かどうか比較する必要があり、メンバーが等しい場合は同じです)。オブジェクトは理論的には、他のオブジェクトとの比較、等価性、相対的順序などの最適な方法を知っています。したがって、非常に特殊な、おそらく誤ったロジックをハードコーディングするのではなく、オブジェクト指向の性質オブジェクトが他のものと等しいかどうかをオブジェクトに伝えさせます。

0

特に言及されていないので、VB.NETタグはこの質問には含まれていないはずですが、IsObject.ReferenceEqualsと同等であり、その呼び出しの代わりに常に使用できます。

0

参照は少し速いかもしれません。前述のように、オーバーロードされたEquals演算子が呼び出されていないことを確認します。また、ReferenceEqualsは、オーバーロードされたEquals演算子の実装に応じて、おそらくは2つではなく1つの比較が実行されることを保証します。オーバーロードされた演算子がReferenceEquals自体を最初のステートメントとして使用している可能性は非常に高いですが。

私は個人的にはReferenceEqualsを使用しますが、私は実際に最後のクロックサイクル(1秒あたり何百万回も呼び出される可能性のある場所)を絞るために本当に微調整している場所でのみ使用します。または、ジェネリックスの場合のように、私がそのタイプを制御できないとき。 ...しかし、パフォーマンスが本当に重要なときだけ再び。 C#7で

+2

演算子は仮想ではありません。実行時の型ではなく、*コンパイル時の型*です。ジェネリックの場合、 '=='演算子をオーバーロードする型に対する制約がない限り、 '=='を使うと常にオブジェクトのオーバーロードが使用されます。これはチェックを行わずに単純に行う必要があります'ReferenceEquals'を呼び出します。そのような場合、機能的に同等であるだけでなく、パフォーマンスも事実上同じになります。これはジェネリックスを 'ReferenceEquals'ではなく' == 'を使う*安全な*時間の1つにします。 – Servy

6

、あなたが使用することができます。

if (!(myObject is null)) 

それは

if (!ReferenceEquals(myObject, null)) 
関連する問題