为什么可以';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,以获得一个非常全面的解释,解释为什么会出现这种情况
这是因为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。同样,它不会直接回答你的问题,但提供了一种可能替代你预期目标的方法。