为什么Distinct不能在这个LINQ查询中工作?

时间:2015-03-19 08:11:31

标签: c# linq linq-to-objects

在下面的查询中,Distinct来电似乎没有做任何事情:

using (var db = new AccountsDbContext())
{
    var uniques = db.AccountMappings
        .Select(m => new CanvasAccount { UserName = m.CanvasUser, Password = m.CanvasPassword })
        .OrderBy(m => m.UserName)
        .ToList()
        .Distinct(new CanvasAccountComparer());
    accounts.AddRange(uniques);
}

此查询返回三个CanvasAccount个对象,但其中两个具有完全相同的用户名和密码。我的比较如下:

class CanvasAccountComparer : IEqualityComparer<CanvasAccount>
{
    public bool Equals(CanvasAccount x, CanvasAccount y)
    {
        return (x.UserName.ToLower() == y.UserName.ToLower()) && (x.Password == y.Password);
    }

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

1 个答案:

答案 0 :(得分:4)

你的比较器坏了 - 两个相同的对象不必返回相同的哈希码。平等和哈希码生成必须彼此一致。您可以使用以下内容解决此问题:

public int GetHashCode(CanvasAccount obj)
{
    int hash = 23;
    hash = hash * 31 + obj.UserName.ToLower().GetHashCode();
    hash = hash * 31 + obj.Password.GetHashCode();
    return hash;
}

注意:

  • 使用ToLower()并不是执行不区分大小写的比较的好方法。这里有各种各样的古怪文化。理想情况下,请改用StringComparer
  • 上面的代码假设PasswordUserName都是非空的。如果其中任何一个可以为null,那么您需要检查它。
  • 我希望此代码并不代表您使用纯文本密码。请注意,如果密码被哈希并加盐,则两个相同的纯文本密码可能会有不同的哈希值。[/ li>