Why can't I compare a KeyValuePair with default

后端 未结 6 1908
Happy的楠姐
Happy的楠姐 2020-12-30 19:25

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

if (myString == default(string))

However I g

相关标签:
6条回答
  • 2020-12-30 19:53

    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.

    0 讨论(0)
  • 2020-12-30 19:56

    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.

    0 讨论(0)
  • 2020-12-30 20:02

    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.

    0 讨论(0)
  • 2020-12-30 20:05

    (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?

    0 讨论(0)
  • 2020-12-30 20:10

    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.

    0 讨论(0)
  • 2020-12-30 20:17

    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.

    0 讨论(0)
提交回复
热议问题