ちらしの裏 「等値性(等価性,同値性とも)と同一性」の書きかけ

こないだの.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();
  }
}