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'!=运算符,这是简单的引用比较。T可能重载/替换的含义并不重要!=,例如string重载以通过值而不是引用来比较它。因此,如果您希望进行值比较,那么以这种方式比较泛型类型是不正确的,例如,具有值的两个字符串"New"可能new1 != new2true.

你可以使用你的EqualityComparer<T>.Default代码,它可以使用T's overrideof object.Equals(object),或者你可以使用 static object.Equals(object, object),它也使用类型的覆盖相等比较。这里唯一的主要区别是,如果存在的话,EqualityComparer<T>.Default它将更喜欢使用 提供的实现。IEquatable<T>

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

The==是一个可以被类重载的运算符。因此,当两个字符串(即使它们是不同的实例)相等时,字符串类将重载此运算符以返回 true。

Object不会重载此运算符,这意味着==for Objects 检查它是否是相同的实例- 它不是。

泛型在编译期间没有类型,因此运算符将被编译为对象的运算符而不是字符串的运算符,并且将失败,即使比较的 ACTUAL 实例是字符串类型。

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 回答