简体   繁体   中英

Linq Except ignoring Custom comparer?

In this toy code:

void Main()
{
    var x = new string[] {"abc", "DEF"};
    var y = new string[] {"ABC", "def"};
    var c = new CompareCI();
    var z = x.Except(y, c);
    foreach (var s in z) Console.WriteLine(s);
}

private class CompareCI : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(string obj)
    {
        return obj.GetHashCode();
    }
}

It seems like the Except method is ignoring my customer comparer. I get these results:

abc
DEF

Which looks like the case is not being ignored. Also, when I ran it under debug and put a breakpoint at the call to string.Equals in the Customer Comparer, the breakpoint never hit, although the code ran and I got the result I posted. i expected no results, since the sequences are equal if case is ignored.

Guess I'm doing something wrong, but I need a second pair of eyes to spot it.

Debugging your code shows that GetHashCode() is called but not Equals().

I think this is because two equal object must have equal hashcodes AND return true from Equals(). If the hashcodes are different then they cannot be equal, so there is no need to run the Equals() function.

Your code would work if the hashing function was case-insensitive, obj.ToUpper().GetHashCode().

.NET Framework already provides a StringComparer Class , that uses specific case and culture-based or ordinal comparison rules - so in this case there is no need to create a custom comparer.

This will work:

var x = new string[] { "abc", "DEF" };
var y = new string[] { "ABC", "def" };
var z = x.Except(y, StringComparer.OrdinalIgnoreCase);

Rui Jarimba的建议使用StringComparer.OriginalIgnoreCase起作用。

Modify your comparer:

public int GetHashCode(string obj)
{
    return 0;
}

Now all items will have the same hash: 0 - which means item x and y may be the same so calling Equals is required.

However, this is not recommended because returning just 0 in GetHashCode will cause performance problems.

Best option is to use built-in StringComparer.OrdinalIgnoreCase equality comparer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM