为什么可以';t我将KeyValuePair<;TKey、TValue>;默认情况下

本文关键字:TValue TKey gt 情况下 默认 lt 我将 为什么 KeyValuePair | 更新日期: 2023-09-27 17:59:16

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

if (myString == default(string))

然而,当我尝试在默认KeyValuePair和KeyValuePair上运行相等比较时,会出现以下异常

代码示例(来自预扩展方法,proto lambda static 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<字符串,对象>'和'System.Collections.Generic.KeyValuePair<字符串,对象>'

这是因为作为一个结构,KeyValuePair不可以为null吗?如果是这样的话,为什么要实现默认值来处理不可为null的类型?

编辑

为了记录在案,我选择了@Chris Hannon作为选择答案,因为他给了我我想要的,最优雅的选择,以及简洁的解释,然而,我鼓励阅读@Dasuraga,以获得一个非常全面的解释,解释为什么会出现这种情况

为什么可以';t我将KeyValuePair<;TKey、TValue>;默认情况下

这是因为KeyValuePair<TKey, TValue>没有定义自定义==运算符,也没有包含在可以使用它的预定义值类型列表中。

这里有一个指向该操作员MSDN文档的链接。

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

在这种情况下,由于这不是您可以控制的结构,因此进行相等性检查的最佳选择是调用default(KeyValuePair<TKey,TValue>).Equals(pair)

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

正如错误所说,KeyValuePairs没有相等测试(即没有内置的比较方法)。这样做的原因是为了避免对KeyValuePairs的类型施加约束(在许多情况下,永远不会进行键值比较)。

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

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

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,àla strcmp。a.比较To(b)==0表示a和b"相同"(在值上,而不是同一对象)。

所以这个函数将取两个KVP(k,v)和(k’,v’),并且当且仅当k==k’和v==v’(在直觉意义上)时返回true。


但这有必要吗?您遇到问题的测试似乎是基于对FirstOrDefault返回的某种验证。

但你的函数被称为FirstOrDefault是有原因的:

返回满足条件或默认值,如果没有这样的元素找到

(重点矿井)

如果找不到东西,此函数将返回默认值,这意味着如果谓词未经验证,则会得到一个等于(default(TKey),default(TValue)的KeyValuePair。

因此,您的代码(打算)检查是否配对。键==默认值(TKey),只能返回默认值(TKey)。这不是更有意义的返回配对。关键从一开始?

为了在任何类或结构上使用"=="相等运算符,它需要覆盖该运算符: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在评论中纠正我的那样,类显然不需要覆盖等式运算符,"=="才有效。它会编译得很好,并进行引用相等性检查。我的错误。

它失败的原因与以下相同:

var kvp = new KeyValuePair<string,string>("a","b");
var res = kvp == kvp;

线索自然在错误消息中。(与default无关)。

Operator '==' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,string>' and 'System.Collections.Generic.KeyValuePair<string,string>'

没有为KeyValuePair<T,U>定义运算符==

错误消息FTW。

快乐的编码。

默认值是标量类型。

问自己这个问题:KVP具有默认值是什么意思?

对于非标量,默认值是从调用nil构造函数中获得的值。假设KVP Equals执行实例标识比较,我希望它返回false,因为每次调用构造函数时都会得到一个新对象。

这是一个略有不同的方向,但我假设您查询了一个Dictionary来获得这个结果,然后您想检查它是否返回了有效的结果。

我发现更好的方法是查询出实际值,而不是整个KeyValuePair,如下所示:

var valitem=MyDict。价值观FirstOrDefault(x=>x。Something==aVar);

现在您可以检查valitem是否为null。同样,它不会直接回答你的问题,但提供了一种可能替代你预期目标的方法。