2013-11-08 2 views
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".
Возможно, вас спросили тысячу раз, но я все еще не понимаю, это должно быть связано с использованием дженериков?

+0

Я в немного спешки, так что я не могу дать вам правильный ответ прямо сейчас, но попробуйте '' где T: IEquatable ''. http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx Не уверен, хотя. –

ответ

1

Следующий код:

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

Рассмотренное во время компиляции, а не во время выполнения, чтобы использовать object «ы != оператора, который является простой ссылкой сравнения. Не имеет значения, что T может overload/replace значение !=, например string's overloading, чтобы сравнить его через значение вместо ссылки. Таким образом, неверно сравнивать типичные типы таким образом, если вы ожидаете сравнения значений и, например, две строки со значением "New" возможно new1 != new2 be true.

Вы можете использовать свой EqualityComparer<T>.Default код, который может использовать T «s override из object.Equals(object), или вы можете использовать статический object.Equals(object, object), который также использует перекрытое сравнение равноправия типа. Единственное существенное отличие здесь состоит в том, что EqualityComparer<T>.Default предпочтет использовать реализацию, предоставляемую IEquatable<T>, если она существует.

if (!object.Equals(value, defaultView.CurrentItem)) 
+0

Осторожно со словом «переопределить». '==' и '! =' операторы реализуются как статические методы, которые нельзя переопределить. Вместо этого я бы сказал «переопределен». – dcastro

+0

Я не понял разрешения во время компиляции. Также object.Equals работает одинаково хорошо и выглядит несколько более естественным. – Gerard

+2

Разрешение происходит во время компиляции именно потому, что это статические методы, которые не имеют понятия наследования. – dcastro

1

== является оператором, который может быть перегружен классами. Следовательно, класс String будет перегружать этот оператор, чтобы возвращать true, когда обе строки (даже если они являются разными экземплярами) равны.

Object не перегружает этот оператор, означает, что == для объектов проверки, если его же экземпляр - что это не так.

Генералы не имеют типа во время компиляции, поэтому Оператор будет скомпилирован как Оператор объекта, а не оператор String, и завершится с ошибкой, даже если сравниваемые экземпляры ACTUAL относятся к типу String.

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 
Смежные вопросы