在课程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 :(得分:1)
以下代码:
if (value != (T)defaultView.CurrentItem)
在编译时而不是运行时解析使用object
的{{1}}运算符,这是简单的引用比较。 !=
可能overload/replace T
的含义并不重要,例如string
's overloading通过值而不是引用来比较它。因此,如果您期望进行价值比较,那么以这种方式比较通用类型是不正确的。值为!=
的两个字符串可能"New"
为new1 != new2
。
您可以使用EqualityComparer<T>.Default
代码,该代码可以使用true
T
object.Equals(object)
,或者您可以使用静态object.Equals(object, object)
,它还使用了类型的重写等式比较。这里唯一的主要区别是override
会更喜欢使用EqualityComparer<T>.Default
提供的实现(如果存在)。
IEquatable<T>
答案 1 :(得分:1)
==
是一个可以按类重载的运算符。因此,当两个字符串(即使它们是不同的实例)相等时,String类将重载此运算符以返回true。
Object
不会使此运算符超载,意味着对象的==
会检查相同的实例 - 它不是。
泛型在编译期间没有Type,因此运算符将被编译为Object的运算符而不是String的运算符并且将失败,即使比较的ACTUAL实例是Type 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