c# - IEnumerable.Intersect 与自定义比较器,不了解行为

标签 c# linq

我正在尝试为相交创建自定义 IEqualityComparer 以使用 Regex 比较字符串,但我真的不明白它在做什么。

这是来自 LinqPad 测试的代码。

比较器:

public class RegexEqualityComparer : EqualityComparer<string>
{
    public RegexEqualityComparer(string pattern, RegexOptions options = RegexOptions.None)
    {
        _re = new Regex(pattern, options);
    }

    public RegexEqualityComparer(Regex re)
    {
        _re = re;
    }

    public override bool Equals(string x, string y)
    {           
        bool res = false;

        if (Object.ReferenceEquals(x, y)) 
            res = true;
        else if (x != null && y != null)
            res = _re.IsMatch(x) && _re.IsMatch(y);

        String.Format("RES: {0}, {1} = {2}", new object[] { x, y, res }).Dump();

        return res;            
    }

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

    // ------------------------------------------------------------------------------------------------------------------------------------------------ 
    private Regex _re;
}

调用方式:

RegexEqualityComparer comparer = new RegexEqualityComparer(@"^-");

new string[] { "1", "-4" }.Intersect(new string[] { "1", "-" }, comparer).Dump();

我希望这能给我 { "1", "-4"} - 根据相等比较器,来自 set1 的两个元素都出现在 set2 中;它实际给出的是:

RES: 1, 1 = True
{ "1" }

真正让我感到困惑的是,根据比较器中的 LinqPad Dump(),它甚至不会尝试将 -4 与任何东西进行比较 -唯一的转储是 RES: 1, 1 = True

我确定我在这里遗漏了一些明显的东西,但根本看不到它!

最佳答案

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

如果 Equals(a, b) 则要求 GetHashCode(a) == GetHashCode(b)。这不是由您的 EqualityComparer 保证的,这个错误意味着 Intersect() 调用找不到匹配值。

与您的 Equals 相对应的足够明智的实现是:

public override int GetHashCode(string obj)
{
  if (obj == null) return 0;
  if (_re.IsMatch(obj)) return 1;
  return obj.GetHashCode(); // catch the reference-equals part for non-matches.
}

具有相同字符的两个字符串将被视为不相等的事实(即它认为 new string('1', 1) 不同于 "1" ) 可能是故意的,也可能是一个错误。也许 ReferenceEquals() 应该是字符串的 ==

关于c# - IEnumerable.Intersect 与自定义比较器,不了解行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41570983/

相关文章:

c# - 如何在 C# 或 F# 中使用 Travis-CI

c# - SaveJpeg 导致 "shadows"具有透明度的伪影

asp.net-mvc - LINQ to Entities无法识别方法异常

c# - 为什么我需要 ToList() 来避免处理上下文错误?

c# - Linq 中的双重或三重 "where"子句

LINQ 获取两个列表的差异 -> 保留重复项

c# - 使用诺基亚 map 的 Windows Phone 8 地理围栏

c# - 在C#中匹配varName $ [index]和@varName [index](正则表达式帮助)

c# - 加起来等于给定自然数的总和组合

c# - 在公共(public)字段上加入 C# 中的两个列表的最有效方法是什么?