首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有list<T>多元素的“包含”的Linq查询筛选器

带有list<T>多元素的“包含”的Linq查询筛选器
EN

Stack Overflow用户
提问于 2016-06-17 21:46:18
回答 3查看 992关注 0票数 1

我想通过Linq查询一个列表,但在我的示例中通过包含两个元素(名称、状态)的另一个列表进行筛选。这是受一个老问题的启发,我已经适应了我的问题。LINQ: "contains" and a Lambda query (在这个答案中,它只工作于一个元素,即状态)

我尝试使用“包含”方法,但没有成功地过滤我的列表。

我应该得到的结果只有两栋楼(两栋,五座),有人知道我在哪里停下来了吗?

谢谢

区块报价

代码语言:javascript
复制
    public class Building
    {
        public enum StatusType
        {
            open,
            closed,
            weird,
        };

        public string Name { get; set; }
        public StatusType Status { get; set; }
    }

    private static readonly List<Building> BuildingList = new List<Building>()
    {
        new Building() {Name = "one", Status = Building.StatusType.open},
        new Building() {Name = "two", Status = Building.StatusType.closed},
        new Building() {Name = "three", Status = Building.StatusType.weird},
        new Building() {Name = "four", Status = Building.StatusType.open},
        new Building() {Name = "five", Status = Building.StatusType.closed},
        new Building() {Name = "six", Status = Building.StatusType.weird},
    };

    private  void GetResult()
    {
        var buildingSelect = new List<Building>
        {
            new Building() {Name = "two", Status = Building.StatusType.closed},
            new Building() {Name = "five", Status = Building.StatusType.closed}
        };

        var q = (from building in BuildingList
            where buildingSelect.Contains(building.Name, building.Status)
            select building).ToList();

        dataGridView1.DataSource = q;
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-18 02:33:52

LINQ的主要问题是您正在尝试比较两个Buildings的相等性,因为Building没有实现IEquatable<Building>或覆盖object.Equals,所以LINQ只能通过它们的引用进行比较。

解决这个问题的一种方法是手动指定哪些属性可以按照@Wayne的答案进行相等的比较。

另一种方法是,如果Building实例要被值而不是引用等同,那么实现IEquatable<Building>并覆盖object.Equals

代码语言:javascript
复制
public class Building : IEquatable<Building>
{
    public Building(string name, StatusType status)
    {
        Name = name;
        Status = status;
    }

    public enum StatusType
    {
        open,
        closed,
        weird,
    };

    public string Name { get; }

    public StatusType Status { get; }

    public static bool operator ==(Building left, Building right)
        => Equals(left, right);

    public static bool operator !=(Building left, Building right)
        => !Equals(left, right);

    public override bool Equals(object obj) => Equals(obj as Building);

    public bool Equals(Building other)
    {
        if (ReferenceEquals(this, other))
        {
            return true;
        }

        if (ReferenceEquals(other, null) || GetType() != other.GetType())
        {
            return false;
        }

        return Name == other.Name && Status == other.Status;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + Name?.GetHashCode() ?? 0;
            hash = hash * 23 + Status.GetHashCode();
            return hash;
        }
    }
}

这样,您的原始代码就可以工作了,因为List.Contains现在将使用您的IEquatable<Building>实现来检查是否相等。

票数 1
EN

Stack Overflow用户

发布于 2016-06-18 01:40:44

你是说像这样的事?

代码语言:javascript
复制
    var q = from b in BuildingList
        from bs in buildingSelect
        where b.Name == bs.Name && b.Status == bs.Status
        select b;

或者也许:

代码语言:javascript
复制
    var q = from b in BuildingList
        join bs in buildingSelect
        on new { b.Name, b.Status } equals new { bs.Name, bs.Status }
        select b;
票数 0
EN

Stack Overflow用户

发布于 2016-06-18 02:37:10

如果这样做有意义的话,可以重写类本身中的等式。

或者通常使用Any()进行检查,如下所示:

代码语言:javascript
复制
    var q = (from building in BuildingList
        where buildingSelect.Any(b => b.Name == building.Name 
                                      && b.Status == building.Status)
        select building).ToList();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37890816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档