0

クラスpublic class ViewModelCollection<T> : ObservableCollection<T> where T : class
には、次のメソッドがあります。

public T CurrentItem
{
    get { return defaultView.CurrentItem as T; }
    set
    {
        // ** wrong when T is of type string ** if (value != defaultView.CurrentItem)
        // ** wrong when T is of type string ** if (value != (T)defaultView.CurrentItem)
        if (!EqualityComparer<T>.Default.Equals(value, (T)defaultView.CurrentItem))
        {
            defaultView.MoveCurrentTo(value);
            OnPropertyChanged(new PropertyChangedEventArgs("CurrentItem"));
        }
        else return;
    }
}

通常のオペレーターがなぜその==ように振る舞うのか理解できません"New" != "New"
おそらく何千回も尋ねられましたが、まだわかりません。ジェネリックの使用と関係があるのでしょうか?

4

2 に答える 2

1

次のコード:

if (value != (T)defaultView.CurrentItem)

実行時ではなくコンパイル時に解決され、単純な参照比較であるobject's演算子を使用します。参照ではなく値を介して比較するための のオーバーロードなど、 の意味をオーバーロード/置換してもかまい!=ません。したがって、値の比較を期待している場合、そのような方法でジェネリック型を比較す​​るのは正しくありません。たとえば、値を持つ 2 つの文字列が.T!=string"New"new1 != new2true

のofを利用できるEqualityComparer<T>.Defaultコードを使用することも、型のオーバーライドされた等値比較も使用する static を使用することもできます。ここでの唯一の大きな違いは、が提供する実装が存在する場合は、それを優先して使用することです。Toverrideobject.Equals(object)object.Equals(object, object)EqualityComparer<T>.DefaultIEquatable<T>

if (!object.Equals(value, defaultView.CurrentItem))
于 2013-11-08T14:36:32.480 に答える
1

==、クラスによってオーバーロードできる演算子です。したがって、両方の文字列が (インスタンスが異なっていても) 等しい場合、String クラスはこの演算子をオーバーロードして true を返します。

Objectこの演算子をオーバーロードしません。つまり、オブジェクトが同じインスタンス==であるかどうかをチェックしますが、そうではありません。

ジェネリックはコンパイル時に型を持たないため、演算子は文字列の演算子ではなくオブジェクトの演算子としてコンパイルされ、比較される実際のインスタンスが文字列型であっても失敗します。

String a = "Test";
String b = "Test";

MessageBox.Show((a == b).ToString()); 
//True, even if different instance: == compiled for string

Object c = new object();
Object d = new object();

MessageBox.Show((c == d).ToString()); 
//False, cause different instance: == compiled for object

次の例も参照してください。

Testこのクラスは、比較すると、等しいすべてのインスタンスをスレッド化します==-なぜなら私はそう言ったからです! (演算子定義が常に比較される型と演算子の実装方法に依存することを示すための例)

 private class Test{

        private string s;

        public Test(string s)
        {
            this.s = s;
        }

        public static Boolean operator ==(Test c1, Test c2)
        {
            return true;
        }

        public static Boolean operator !=(Test c1, Test c2)
        {
            return false;
        }
    }

    Test x = new Test("Hello");
    Test y = new Test("World");

     MessageBox.Show((x == y).ToString()); // True
于 2013-11-08T14:38:32.793 に答える