为什么我无法将KeyValuePair <TKey,TValue>与默认值进行比较

在.Net 2.5中,我通常可以获得值与其类型默认值之间的等式比较(==)

if (myString == default(string))

但是,当我尝试在默认的KeyValuePair和KeyValuePair上运行相等比较时,我得到以下异常

代码示例(来自预扩展方法,proto-lambda静态ListUtilities类:))

public static TKey 
        FirstKeyOrDefault<TKey, TValue>(Dictionary<TKey, TValue> lookups, 
                   Predicate<KeyValuePair<TKey, TValue>> predicate)
{
    KeyValuePair<TKey, TValue> pair = FirstOrDefault(lookups, predicate);

    return pair == default(KeyValuePair<TKey, TValue>) ? 
                   default(TKey) : pair.Key;
}

例外:

运算符'=='不能应用于'System.Collections.Generic.KeyValuePair <string,object>'和'System.Collections.Generic.KeyValuePair <string,object>'类型的操作数

这是否是因为,作为一个结构,KeyValuePair不能为空? 如果是这种情况,那么为什么(可能是默认)被实现来处理不可为空的类型呢?

编辑

为了记录,我选择了@Chris Hannon作为选定的答案,因为他给了我我正在寻找的东西,最优雅的选择以及简洁的解释,但是我鼓励读@Dasuraga来解释为什么这是一个非常全面的解释案子


发生这种情况是因为KeyValuePair<TKey, TValue>未定义自定义==运算符,并且未包含在可使用它的预定义值类型列表中。

这里是该运营商的MSDN文档的链接。

对于预定义的值类型,如果操作数的值相等,则相等运算符(==)返回true,否则返回false。

在这种情况下,最好的选择是平等检查,因为这不是一个你可以控制的结构,而是调用default(KeyValuePair<TKey,TValue>).Equals(pair)来代替。


(如果你不关心与这个错误有关的泛型讨论,你可以跳到最后以获得“真实”答案)

正如错误所述,KeyValuePairs没有相等性测试(即没有内置比较方法)。 原因是为了避免对KeyValuePairs的类型设置约束(有很多情况下,不会进行关键的值比较)。

显然,如果你想比较KeyValuePairs,我想你会想要检查键和值是否相等。 但这意味着一大堆事情,特别是TKey和TValue都是可比类型(即它们实现了IComparable接口)

您可以在keyvaluepairs之间编写自己的比较函数,例如:

static bool KeyValueEqual<TKey , TValue>(KeyValuePair<TKey, TValue> fst, 
                                          KeyValuePair<TKey, TValue> snd) 
                                         where  TValue:IComparable
                                         where  TKey:IComparable
        {
            return (fst.Value.CompareTo(snd.Value)==0)
                     && (snd.Key.CompareTo(fst.Key)==0);
        }

(请原谅可怕的缩进)

这里我们强加TKey和TValue是可比的(通过CompareTo成员函数)。

当两个对象相等时,CompareTo函数(如为预定义类型定义的)返回0。 a.ComparesTo(b)== 0表示a和b是“相同的”(在值中,而不是相同的对象)。

所以这个函数需要两个KVP(k,v)和(k',v')并且当且仅当k == k'和v == v'(在直观意义上)才会返回true。


但这是必要的吗? 看起来你的测试问题是基于对FirstOrDefault返回的某种验证。

但是有一个原因叫做FirstOrDefault:

如果未找到此元素,则返回满足条件或默认值的序列的第一个元素

(强调我的)

如果没有找到某个东西,这个函数返回默认值 ,这意味着如果你的谓词没有被验证,你会得到一个KeyValuePair等于(默认(TKey),默认值(TValue)。

因此你的代码(打算)检查pair.Key == default(TKey), 反正返回默认的(TKey) 。 从一开始就返回pair.Key不是更有意义吗?


为了在任何类或结构上使用“==”等号运算符,它需要覆盖该运算符:http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80)。 ASPX

KeyValuePair不,因此你会得到编译错误。 请注意,如果你只是试试这个,你会得到同样的错误:

var k1 = new KeyValuePair<int,string>();
var k2 = new KeyValuePair<int,string>();

bool b = k1 == k2; //compile error

编辑:正如Eric Lippert在评论中纠正了我,类显然不需要覆盖“==”的相等运算符是有效的。 它会很好地编译并进行参考平等检查。 我的错。

链接地址: http://www.djcxy.com/p/58613.html

上一篇: Why can't I compare a KeyValuePair<TKey, TValue> with default

下一篇: 'is' operator behaves unexpectedly with non