简体   繁体   English

Linq除了忽略自定义比较器?

[英]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. 似乎Except方法正在忽略我的客户比较器。 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. 另外,当我在调试下运行它并在对string的调用处放置一个断点时,在客户比较器中等于断点,尽管代码已运行并且得到了发布的结果,但断点从未命中。 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(). 调试代码显示,调用了GetHashCode(),但未调用Equals()。

I think this is because two equal object must have equal hashcodes AND return true from Equals(). 我认为这是因为两个相等的对象必须具有相等的哈希码,并从Equals()返回true。 If the hashcodes are different then they cannot be equal, so there is no need to run the Equals() function. 如果哈希码不同,则它们不能相等,因此无需运行Equals()函数。

Your code would work if the hashing function was case-insensitive, obj.ToUpper().GetHashCode(). 如果哈希函数不区分大小写,即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. .NET Framework已经提供了StringComparer类该类使用特定的大小写和基于区域性的或有序的比较规则-因此,在这种情况下,无需创建自定义比较器。

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. 现在所有项目将具有相同的哈希值: 0这意味着项目xy 可能相同,因此需要调用Equals

However, this is not recommended because returning just 0 in GetHashCode will cause performance problems. 但是,不建议这样做,因为在GetHashCode中仅返回0会导致性能问题。

Best option is to use built-in StringComparer.OrdinalIgnoreCase equality comparer. 最好的选择是使用内置的StringComparer.OrdinalIgnoreCase相等比较器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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