ちらしの裏 「等値性(等価性,同値性とも)と同一性」の書きかけ
こないだの.NETクイズの回答の書きかけメモ。
C#ではどうしようもないときを除いて「==」使え、ってことでいいのかな?
つっこみ、過不足の指摘、ご意見、大歓迎です。
== | x.Equals( x ) | Equals( x, x ) | ReferenceEquals( x, x ) | |
---|---|---|---|---|
組み込みの値型 | 等値性 | 等値性 | - | - |
NaN ( double, float ) (注:IsNaNを使うべき) |
等値性 ただし常に False |
等値性 ただし常に True |
- [box化して等値性を 調べると True] |
- |
ユーザ定義の値型 ( struct ) |
ユーザ定義がなければ コンパイルエラー (ユーザ定義は 等値性 であるべき) |
- (ユーザ定義は 等値性 であるべき) [ユーザ定義がなければ 等値性 ( box化を伴い,リフレクションを使う )] |
- (ユーザ定義は 等値性 であるべき) [ユーザ定義がなければ 等値性 ( box化を伴い,リフレクションを使う )] |
- |
box化した値型 | 同一性 | 等値性 | 等値性 | 同一性 [box化していない一つの値を比較しようとしても 各々boxされるため、同一にはならない] |
string | 等値性 | 等値性 | 等値性 | 同一性 |
class | (基本的に) 同一性 | (基本的に) 同一性 | (基本的に) 同一性 | 同一性 |
値を表す class 例えばUriなど |
等値性 (であるべき) | 等値性 (であるべき) | 等値性 (であるべき) | 同一性 |
using System; struct S { public int Value; } class C { public int Value; } class Program { static void Main() { int n = 1, m = 1; Console.WriteLine( "int" ); Console.WriteLine( "n == m : {0}", n == m ); Console.WriteLine( "n.Equals( m ) : {0}", n.Equals( m ) ); Console.WriteLine( "n.Equals( ( object ) m ) : {0}", n.Equals( ( object ) m ) ); Console.WriteLine( "int.Equals( n, m ) : {0}", int.Equals( n, m ) ); Console.WriteLine( "int.ReferenceEquals( n, m ) : {0}", int.ReferenceEquals( n, m ) ); Console.WriteLine(); object o = n, p = 1; Console.WriteLine( "object (boxed int)" ); Console.WriteLine( "o == p : {0}", o == p ); Console.WriteLine( "o.Equals( p ) : {0}", o.Equals( p ) ); Console.WriteLine( "object.Equals( o, p ) : {0}", object.Equals( o, p ) ); Console.WriteLine( "object.ReferenceEquals( o, p ) : {0}", object.ReferenceEquals( o, p ) Console.WriteLine(); double nan = double.NaN; Console.WriteLine( "double" ); Console.WriteLine( "nan == nan : {0}", nan == nan ); Console.WriteLine( "nan.Equals( nan ) : {0}", nan.Equals( nan ) ); Console.WriteLine( "object.Equals( nan, nan ) : {0}", object.Equals( nan, nan ) ); Console.WriteLine( "object.ReferenceEquals( nan, nan ) : {0}", object.ReferenceEquals( nannan ) ); Console.WriteLine(); S s0 = new S(), s1 = new S(); s0.Value = 1; s1.Value = 1; Console.WriteLine( "struct" ); //Console.WriteLine( s0 == s1 ); Console.WriteLine( "s0.Equals( s1 ) : {0}", s0.Equals( s1 ) ); Console.WriteLine( "object.Equals( s0, s1 ) : {0}", object.Equals( s0, s1 ) ); Console.WriteLine( "object.ReferenceEquals( s0, s1 ) : {0}", object.ReferenceEquals( s0, s) ); Console.WriteLine(); C c0 = new C(), c1 = new C(); c0.Value = 1; c1.Value = 1; Console.WriteLine( "class" ); Console.WriteLine( "c0 == c1 : {0}", c0 == c1 ); Console.WriteLine( "c0.Equals( c1 ) : {0}", c0.Equals( c1 ) ); Console.WriteLine( "object.Equals( c0, c1 ) : {0}", object.Equals( c0, c1 ) ); Console.WriteLine( "object.ReferenceEquals( c0, c1 ) : {0}", object.ReferenceEquals( c0, c) ); Console.WriteLine(); string str0 = "abc", str1 = "ab"; Console.WriteLine( "ごみ {0}", str0 == str1 ); str1 = str1 + "c"; Console.WriteLine( "string" ); Console.WriteLine( "str0 == str1 : {0}", str0 == str1 ); Console.WriteLine( "str0.Equals( str1 ) : {0}", str0.Equals( str1 ) ); Console.WriteLine( "string.Equals( str0, str1 ) : {0}", string.Equals( str0, str1 ) ); Console.WriteLine( "string.ReferenceEquals( str0, str1 ) : {0}", string.ReferenceEquals( s0, str1 ) ); Console.ReadKey(); } }