2015-12-25 10 views
6

C#で単純な単独リンクリストを実装しようとしているとき、int値でボックス化された2つのオブジェクト型変数を比較すると==は機能しませんしかし.Equalsが動作します。同じint値でボックス化された2つのオブジェクト型変数を比較する際に==が機能しない理由

なぜそうであるかを確認したいと思っていました。私は交換した場合、しかし、

/// <summary> 
/// <param name="d">Data to be searched in all the nodes of a singly linked list 
/// Traverses through each node of a singly linked list and searches for an element 
/// <returns>Node if the searched element exists else null </returns> 
public Node Search(object d) 
{ 
    Node temp = head; 

    while (temp != null) 
    { 
     if (temp.Data.Equals(d)) 
     { 
      return temp; 
     } 

     temp = temp.Next; 
    } 

    return null; 
} 

-

以下のスニペットは、以下のコードは、Object型の値の単独リンクリストや検索を横断

public class Node { 
    /// <summary> 
    /// Data contained in the node 
    /// </summary> 
    private object Data { get; set; }; 
} 

汎用オブジェクト型のデータプロパティです temp.Dataと

temp.Data.Equals(d) 

== D

temp.Datadの両方が値 '3'を持っていても機能しなくなります。 ==がオブジェクト型変数で動作しない理由は何ですか?

は、ここでの主な機能からの抜粋だ - 私はint型の値3を渡していますし、検索メソッドは、オブジェクトの種類を期待するので、私は信じてい

SinglyLinkedList list = new SinglyLinkedList(); 
list.Insert(1); 
list.Insert(2); 
list.Insert(3); 
list.Insert(4); 
list.Insert(5); 

list.Print(); 

Node mid = list.Search(3); 

、それが成功したオブジェクト型として3箱入りただろう。しかし、なぜ==が機能しないのか分かりませんが、.Equalsはします。

==演算子は値型のみにオーバーロードされていますか?

+3

ジェネリックを使用する必要があります。 – SLaks

+0

はい、これは練習のためのものです。ジェネリックスは既にLinkedListの実装を持っていることに気づいた – Ankit

答えて

9

2つの理由があります。

  • Equals==およびその逆で囲まれた、とリファレンスの同一のデフォルトのチェックによってされていません。

    あなたが.Equals vs ==の仕様で読むことができたよう:

    デフォルトでは、演算子==は、2つの参照が同じものを示すかどうかを判断することによって参照の等価性をテストしますしたがって、参照型はこの機能を得るためにオペレータ==を実装する必要はありません。型が不変である場合、インスタンスに含まれるデータを変更できないことを意味します。不変オブジェクトとして同一であるとみなすことができるため、参照平等ではなく値の等しい比較演算子==をオーバーロードすると便利です。値。オペレータ==を不変でない型でオーバーライドすることは推奨されません。

    オーバーロードされた演算子==実装は例外をスローするべきではありません。オペレータ==をオーバーロードするすべてのタイプは、オペレータ!=もオーバーロードする必要があります。

    あなたにも!=をオーバーライドしていない、とあなたはより良い.Equals.GetHashCodeの両方を上書きすることを警告する場合、コンパイラはエラーをスローしますが。

    したがって、.Equals,==および!=のオーバーライド/オーバーロードは異なるものです。 .Equalsをオーバーライドしても、==!=のオーバーロードには影響しません。結局のところ、==はカスタム演算子です。それを行うことは賢明ではありませんが、平等チェック以外の目的で使用することもできます。

  • さらに事業者は、コンパイル時で解決され

    csharp対話型シェルプログラムを、次の例を見てみましょう:あなたが見ることができるように

    $ csharp 
    Mono C# Shell, type "help;" for help 
    
    Enter statements below. 
    csharp> public class Foo { 
         > 
         > public int data; 
         > 
         > public static bool operator == (Foo f1, Foo f2) { 
         >  return f1.data == f2.data; 
         > } 
         > 
         > public static bool operator != (Foo f1, Foo f2) { 
         > 
         >  return f1.data != f2.data; 
         > } 
         > 
         > } 
    (1,15): warning CS0660: `Foo' defines operator == or operator != but does not override Object.Equals(object o) 
    (1,15): warning CS0661: `Foo' defines operator == or operator != but does not override Object.GetHashCode() 
    csharp> object f = new Foo(); 
    csharp> object f2 = new Foo(); 
    csharp> f == f2 
    false 
    csharp> Foo f3 = f as Foo; 
    csharp> Foo f4 = f2 as Foo; 
    csharp> f3 == f4 
    true 
    

    は、==があなたの場合は異なる結果が得られますオブジェクトをobject、またはFooと呼びます。 objectを使用しているので、コンパイル時にC#が作成できる唯一のバインディングは、参照の等しいものです。

+0

かなりクールな説明。例を引用してくれてありがとう==と!=をオーバーライドして、値を比較するための参照平等を調整することができました。 – Ankit

+1

@Ankit no。演算子をオーバーライドすることはできません。あなたはそれらを過負荷にすることしかできません。 'int'はもちろん' == 'をオーバーロードすることに注意してください。ここで重要な点は、スタティック(コンパイル時)型です。これはオーバーライドではなくオーバーロードなので重要です。 – phoog

+0

コメントありがとう@phoog。あなたのコメントを読んでから、この[link](http://geekswithblogs.net/BlackRabbitCoder/archive/2011/07/07/c.net-little-pitfalls-operators-are-overloaded-not-overridden.aspx)は私を作った演算子はコンパイル時に実際にオーバーロードされ、バインドされており、静的であるためオーバーライドされないことを理解してください。このリンクは、オーバーライドされた演算子の中で仮想メソッドを使用し、次に仮想メソッドをオーバーライドすることができるオペレータオーバーライドの回避策を指摘しています:) – Ankit

5

インスタンスEquals(object)がオーバーロードしている間==試験のSystem.Object実装は、静的Equals(object, object)ように、平等を参照するので、それはですので、実際の値をチェックします。

値の種類を2回入力すると、2つの異なるインスタンスが生成されるため、もちろん参照の一致が失敗します。

演算子は静的であるため、コンパイル時にバインドされるため、動的ディスパッチはありません。すでに参照型でありオブジェクト型変数に代入されているときにボックス化されていない文字列であっても、オペランドの1つがstring以外の静的型を持つ場合は、==演算子との意図しない参照を取得できます。

+0

@ user2864740良い点、ありがとう。編集されました。 – phoog

+0

ありがとうございます。はい、 '=='が行った参照等価チェックは意図しないものでした。私は将来も文字列のためにこれを覚えておきます。 – Ankit

4

演算子==は、コンパイル時の型に基づいて選択されたオーバーロードされた静的関数のようなものです。あなたのケースでは、値のタイプはObjectで、==演算子は参照平等を実装します。

一方、.Equalsは仮想でオーバーライドされているため、実際のタイプに基づいて比較が行われます。

+0

右。 @hege_hegedusに質問の編集をしていただき、 '=='を実装して、参照等価と '.Equals'を実装しています。これは仮想でオーバーライドされ、実際の型を比較します。 – Ankit

関連する問題