web-dev-qa-db-ja.com

これら2つの比較の結果が異なるのはなぜですか?

このコードがtrueを返すのはなぜですか。

new Byte() == new Byte()   // returns true

しかし、このコードはfalseを返します:

new Byte[0] == new Byte[0] // returns false
68
Maxim Zhukov

new Byte()は値タイプを作成し、値によって比較されるためです(デフォルトでは、値0byteが返されます)。そして、new Byte[0]は、参照型であり、参照によって比較される配列を作成します(そして、配列のこれら2つのインスタンスは異なる参照を持ちます)。

詳細については、 値型と参照型 の記事を参照してください。

143

バイトは.NETでは 値型 です。つまり、2つのバイトの値が同じである場合に限り、==演算子はtrueを返します。これは、 値の同等性 とも呼ばれます。

ただし、配列は.NETでは 参照型 です。つまり、==演算子は、メモリ内の同じ配列インスタンスを参照する場合にのみtrueを返します。これは、 参照の同等性またはアイデンティティとも呼ばれます-)

==演算子は、参照型と値型の両方でオーバーロードされる可能性があることに注意してください。たとえば、System.Stringは参照型ですが、文字列の==演算子は、配列内の各文字を順番に比較します。 Equals()および演算子のオーバーロードに関するガイドライン==(C#プログラミングガイド) を参照してください。

配列がまったく同じ値(順番に)含まれているかどうかをテストする場合は、 Enumerable.SequenceEqual==の代わりに。

43
p.s.w.g

参照の比較とは、実際にはポインタアドレスを比較することです。これは、falseを返す理由であり、値アドレスでは、値を比較する必要はありません。

コンパイラは値型をレジスタに格納しようとしますが、レジスタ数が限られているため、参照型がスタックにあるが値がヒープ内のメモリアドレスのアドレスを保持している間、値がスタックにさらに格納されます [Reference] .

ここでの比較では、スタックに存在する値を比較します。最初のケースでは両方が同じですが、2番目のケースではヒープのアドレスが異なります。

reference

10
Zaheer Ahmed

両方のオペランドがタイプbyteである==演算子のオーバーロードがあり、各バイトの値を比較するために実装されています。この場合、2つのゼロバイトがあり、それらは等しいです。

==演算子は配列に対してオーバーロードされないため、2番目のケースでは2つのobjectオペランドを持つオーバーロードが使用され(配列はタイプobjectであるため)、その実装は比較されます。 2つのオブジェクトへの参照。 2つの配列への参照は異なります。

これは、byteが値型であり、配列が参照型であるという事実とは(直接)関係がないことに注意してください。 byte==演算子には、値のセマンティクスがありますのみその実装では演算子の特定のオーバーロードがあるためです。そのオーバーロードが存在しなかった場合、be 2バイトが有効なオペランドとなるオーバーロードがないため、コードまったくコンパイルされませんになります。これは、カスタムstructを作成し、その2つのインスタンスを==operatorと比較することで簡単に確認できます。これらのタイプに==の独自の実装を提供しない限り、コードはコンパイルされません。

1
Servy