如何在C#中从LINQ查询中获取不同的项

本文关键字:获取 查询 中从 LINQ | 更新日期: 2023-09-27 18:21:28

我有一个查询,它是这样定义的,我用它来生成JSON输出。重点是,我已经对它应用了Distinct方法,但它仍然显示重复的项。例如,我有许多值为"Unclassified"的项目,而我只想要其中一个,其他一些值也是如此。这是我的问题:

var results = db.Users.OfType<Business>()
              .Where(b => b.StateID == state && (term == null || b.Description.ToLower().Contains(term.ToLower())))
              .Distinct().Select(x => new { id = x.StateID, value = x.Description }).Take(5).ToList();

知道怎么修吗?我想我需要以某种方式将Distinct具体应用于该值。

如何在C#中从LINQ查询中获取不同的项

我怀疑您需要切换DistinctSelect调用。考虑到您的投影,Distinct将比较比您预期的更多的字段,这可能意味着正在比较的字段不是您实际想要比较的字段。首先调用Select将减少为生成不同列表而进行比较的字段的数量。

var results = db.Users.OfType<Business>()
          .Where(b => b.StateID == state && (term == null ||  b.Description.ToLower().Contains(term.ToLower())))
          .Select(x => new { id = x.StateID, value = x.Description })
          .Distinct()
          .Take(5)
          .ToList();

.NET无法知道如何确定对象中的"相等"。默认情况下,引用类型的相等仅基于引用相等,因此默认情况下所有对象都是不同的。

您可以为Distinct()提供自定义相等比较器。例如,如果您只是在.Name属性上进行比较以确定唯一性,它可能看起来像这样:

class BusinessComparer : IEqualityComparer<Business>
{
    public bool Equals(Business x, Business y)
    {
        if (Object.ReferenceEquals(x, y))
            return true;
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;
        return x.Name == y.Name;
    }
    public int GetHashCode(Business business)
    {
        if (Object.ReferenceEquals(business, null))
            return 0;
        int hashBusinessName = business.Name == null ? 0 : business.Name.GetHashCode();
        return hashProductName;
    }
}

如果这个等式是核心业务逻辑,而不仅仅用于这个特定的比较,那么您甚至可以在Business本身上实现EqualsGetHashCode,以便在其他地方使用等式比较。请注意,这可能是对已经假定引用相等的现有代码的一个突破性更改。

Business类需要覆盖object.Equalsobject.GetHashCode方法并实现IEquatable<T>Distinct方法才能正常工作。

请参阅MSDN示例:Enumerable.Dispinct方法(IEnumerable)

Distinct()通过使用默认的相等比较器比较值,从序列中返回不同的元素。所以你应该创建BusinessEqualityComparer类应该实现IEqualityComparer接口

class BusinessEqualityComparer : IEqualityComparer<Business>
{
    public bool Equals(Business b1, Business b2)
    {
        if (b1.ID == b2.ID)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public int GetHashCode(Business business)
    {
        int hCode = business.ID ^ business.ID ^ business.ID;
        return hCode.GetHashCode();
    }

.Distinct()如果不提供手动比较器,将使用处理类型的默认比较器,该比较器最终将使用Business类的.Equals().GetHashCode()

因此,除非您重写了这些方法,否则.Distinct()将只删除引用方式的重复项。