为什么我不能比较 KeyValuePair和 KeyValuePair默认情况下

发布于 2024-11-15 23:59:52 字数 1026 浏览 1 评论 0原文

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

if (myString == default(string))

运行相等比较时,出现以下异常:

但是,当我尝试对默认 KeyValuePair 和 KeyValuePair代码示例(来自预编译) 扩展方法,原型 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<字符串,对象>' 和 'System.Collections.Generic.KeyValuePair<字符串,对象>'

是因为作为一个结构体,KeyValuePair 不可为空吗?如果是这种情况,为什么默认是为了处理不可为空的类型而实现的?

编辑郑重

声明,我选择@Chris Hannon作为选定的答案,因为他给了我我正在寻找的东西、最优雅的选项和简洁的解释,但是我确实鼓励阅读@Dasuraga关于为什么会出现这种情况的非常全面的解释

In .Net 2.5 I can usually get an equality comparison (==) between a value and its type default

if (myString == default(string))

However I get the following exception when I try to run an equality comparison on a default KeyValuePair and a KeyValuePair

Code Sample (from a pre-extension method, proto-lambda static ListUtilities class :) )

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;
}

Exception:

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

Is it because, as a struct, the KeyValuePair is not nullable? If this is the case, why, as, presumably, default was implemented to handle not nullable types?

EDIT

For the record, I chose @Chris Hannon as selected answer, as he gave me what I was looking for, the most elegant option, and a succinct explanation, however I do encourage reading @Dasuraga for a very comprehensive explanation as to why this is the case

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

紫南 2024-11-22 23:59:52

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

以下是 MSDN 文档的链接 对于该操作员。

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

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

This happens because KeyValuePair<TKey, TValue> does not define a custom == operator and is not included in the predefined list of value types that can use it.

Here is a link to the MSDN documentation for that operator.

For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise.

Your best bet for an equality check in this case, because this is not a struct you have control over, is to call default(KeyValuePair<TKey,TValue>).Equals(pair) instead.

歌入人心 2024-11-22 23:59:52

(如果您不关心与此错误相关的泛型讨论,您可以跳到末尾以获得“真实”答案)

正如错误所示,没有对 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,类似于 strcmp 。 a.ComparesTo(b)==0 表示 a 和 b 是“相同”(在值上,不是同一个对象)。

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


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

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

返回第一个元素
满足条件或的序列
如果没有这样的元素,则为默认
找到了。

(强调我的)

此函数如果未找到某些内容,则返回默认值,这意味着如果您的谓词未经过验证,您将获得一个等于 (default(TKey) 因此,您的代码(打算

)检查是否pair.Key==default(TKey),只是为了返回default(TKey),这不是更有意义吗?返回pair.Key从一开始?

(If you don't care about the generics discussion linked to this error, you can just jump to the end for your "real" answer)

As the error says, there is no equality testing for KeyValuePairs (i.e. there is no built-in comparison method). The reason for this is to avoid having to place constraints on the types of KeyValuePairs (there are many cases where key,value comparisons would never be made).

Obviously if you want to compare thes KeyValuePairs, I'd imagine what you'd want is to check if the keys and values are equal. But this implies a whole mess of things , notably that TKey and TValue are both comparable types (ie they implement the IComparable interface)

You could write your own comparison function between keyvaluepairs, for example:

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);
        }

(Excuse the awful indentation)

Here we impose that TKey and TValue are both comparable (via the CompareTo member function).

The CompareTo function (as defined for pre-defined types) returns 0 when two objects are equal , à la strcmp . a.ComparesTo(b)==0 means a and b are the "same"(in value, not the same object).

so this function would take two KVPs (k,v) and (k',v') and would return true if and only if k==k' and v==v' (in the intuitive sense).


But is this necessary? It seems your test where you're having problems is based on some sort of verification on the return of FirstOrDefault.

But there's a reason your function's called FirstOrDefault:

Returns the first element of the
sequence that satisfies a condition or
a default value if no such element is
found.

(emphasis mine)

This function returns default values if something isn't found, meaning if your predicate isn't verified you'll get a KeyValuePair equal to (default(TKey),default(TValue).

Your code therefore (intends to) check whether pair.Key==default(TKey), only to return default(TKey) anyways. Wouldn't it just make more sense to return pair.Key from the outset?

咆哮 2024-11-22 23:59:52

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

In order you to use the "==" equality operator on any class or struct, it needs to override the operator: http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

KeyValuePair doesn't, and therefore you get the compile error. Note, you'll get the same error if you just try this:

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

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

EDIT: As Eric Lippert corrected me in the comments, classes obviously don't need to override the equality operator for "==" to be valid. It'll compile fine and do a reference equality check. My mistake.

沉睡月亮 2024-11-22 23:59:52

它失败的原因如下:

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 定义运算符 ==

错误消息 FTW。

快乐编码。

It fails for the same reason as the following:

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

The clue is in the error message, naturally. (It has nothing to do with default).

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

The operator == is not defined for KeyValuePair<T,U>.

Error messages FTW.

Happy coding.

你是我的挚爱i 2024-11-22 23:59:52

默认值是针对标量类型的。

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

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

Defaults are pitched at scalar types.

Ask yourself this question: What does it mean for KVP to have a default value?

For non-scalars the default is whatever you get from calling the nil constructor. Assuming that KVP Equals performs instance identity comparison, I would expect it to return false since you get a new object each time the constructor is invoked.

守望孤独 2024-11-22 23:59:52

这方向略有不同,但我假设您查询字典来获取此结果,然后您想要检查它是否返回有效结果。

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

var valitem = MyDict.Values.FirstOrDefault(x=> x.Something == aVar);

现在您可以检查 valitem 是否为空。同样,它并没有直接回答您的问题,而是提供了实现您的预​​期目标的替代方法。

This goes in a slightly different direction, but I am presuming you queried a Dictionary to get this result, and then you want to check if it returned a valid result or not.

I found the better method of doing this was to query out the actual value instead of the whole KeyValuePair, like this:

var valitem = MyDict.Values.FirstOrDefault(x=> x.Something == aVar);

Now you can check if valitem is null or not. Again, it doesn't directly answer your question, but offers what might be a alternative approach to your intended goal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文