fork download
  1. using System;
  2.  
  3. public class Test
  4. {
  5. // コンパイルエラー。whereなしではジェネリック型に演算子を適用できない。
  6. //static void f<T>(T x, T y) {
  7. // Console.WriteLine(x == y ? "OK" : "NG");
  8. //}
  9.  
  10. // where で参照型だけに制限すれば演算子が使えるが、object.== が呼ばれる
  11. static void f<T>(T x, T y) where T: class {
  12. Console.WriteLine(x == y ? "OK" : "NG");
  13. Console.WriteLine("変数の型:" + typeof(T).Name + " / 値の型:" + x.GetType().Name);
  14. }
  15.  
  16. // 明示的に ClassA に制約すれば、そのクラスの == が呼ばれる
  17. static void g<T>(T x, T y) where T: ClassA {
  18. Console.WriteLine(x == y ? "OK" : "NG");
  19. Console.WriteLine("変数の型:" + typeof(T).Name + " / 値の型:" + x.GetType().Name);
  20. }
  21.  
  22. // dynamic を使う場合
  23. static void h(dynamic x, dynamic y) {
  24. Console.WriteLine(x == y ? "OK" : "NG");
  25. Console.WriteLine("値の型:" + x.GetType().Name);
  26. }
  27.  
  28. // 普通は演算子を使わずに object.Equals() を使うべき
  29. static void f1(object x, object y) {
  30. Console.WriteLine(object.Equals(x, y) ? "OK" : "NG");
  31. Console.WriteLine("値の型:" + x.GetType().Name);
  32. }
  33.  
  34. static void Main(string[] args)
  35. {
  36. var x = new ClassA(1);
  37. var y = new ClassA(1);
  38. f(x, y); // NG <= objectクラスの == を呼ぶようコンパイルされるため
  39.  
  40. g(x, y); // OK
  41.  
  42. h(x, y); // OK
  43.  
  44. f1(x, y); // OK
  45. }
  46.  
  47. class ClassA
  48. {
  49. public int Value1 { get; protected set; }
  50.  
  51. // コンストラクタ
  52. public ClassA(int val) { Value1 = val; }
  53.  
  54. // Equals()をオーバーライド
  55. public override bool Equals(object other)
  56. {
  57. Console.WriteLine("ClassA の Equals が呼ばれました。");
  58. var other1 = other as ClassA;
  59. if (object.ReferenceEquals(other1, null)) return false;
  60. return object.Equals(this.Value1, other1.Value1);
  61. }
  62.  
  63. // Equals() が True になる場合は GetHashCode() も同じ値を返す必要がある
  64. public override int GetHashCode()
  65. {
  66. return Value1.GetHashCode();
  67. }
  68.  
  69. // == 演算子を定義
  70. public static bool operator==(ClassA self, ClassA other)
  71. {
  72. Console.WriteLine("ClassA の == が呼ばれました。");
  73. return object.Equals(self.Value1, other.Value1);
  74. }
  75.  
  76. // == を定義するためには != もペアで定義が必要
  77. public static bool operator!=(ClassA self, ClassA other)
  78. {
  79. return !(self == other);
  80. }
  81. }
  82. }
Success #stdin #stdout 0.2s 144000KB
stdin
Standard input is empty
stdout
NG
変数の型:ClassA / 値の型:ClassA
ClassA の == が呼ばれました。
OK
変数の型:ClassA / 値の型:ClassA
ClassA の == が呼ばれました。
OK
値の型:ClassA
ClassA の Equals が呼ばれました。
OK
値の型:ClassA