为什么 Distinct 在此 LINQ 查询中不起作用?
Why is Distinct not working in this LINQ query?
在下面的查询中,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);
}
此查询 returns 三个 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();
}
}
您的比较器已损坏 - 两个相等的对象不一定 return 具有相同的哈希码。相等性和哈希码生成必须彼此一致。您可以使用以下方法解决此问题:
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
。
- 上面的代码假设
Password
和 UserName
都是非空的。如果其中一个可以为 null,则您需要进行检查。
- 我希望这段代码并不意味着您正在使用纯文本密码。请注意,如果密码经过散列和加盐处理,则两个相同的纯文本密码可能具有不同的散列表示形式。
在下面的查询中,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);
}
此查询 returns 三个 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();
}
}
您的比较器已损坏 - 两个相等的对象不一定 return 具有相同的哈希码。相等性和哈希码生成必须彼此一致。您可以使用以下方法解决此问题:
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
。 - 上面的代码假设
Password
和UserName
都是非空的。如果其中一个可以为 null,则您需要进行检查。 - 我希望这段代码并不意味着您正在使用纯文本密码。请注意,如果密码经过散列和加盐处理,则两个相同的纯文本密码可能具有不同的散列表示形式。