Linq查询过滤器&#34;包含&#34;列表<t>多个元素

时间:2016-06-17 21:46:19

标签: linq list contains

我想通过Linq查询列表,但是在我的示例中使用包含两个元素(Name,Status)的其他列表进行过滤。 这是受到我已经适应我的问题的一个老问题的启发。 LINQ: "contains" and a Lambda query (在这个答案中,它仅适用于一个元素,即状态)

我尝试使用&#34; contains&#34;方法,但没有成功过滤我的列表。

我应该只用两栋建筑物(两个,五个)获得一个结果 有没有人知道我在哪里停下来?

谢谢

  

块引用

    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;
    }

3 个答案:

答案 0 :(得分:1)

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

解决这个问题的一种方法是根据@ Wayne的答案手动指定要比较哪些属性。

另一种方式是,如果要将Building个实例等同于其值而不是其引用,请实施IEquatable<Building>并覆盖object.Equals

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 :(得分:0)

你的意思是这样的吗?

    var q = from b in BuildingList
        from bs in buildingSelect
        where b.Name == bs.Name && b.Status == bs.Status
        select b;

或者也许:

    var q = from b in BuildingList
        join bs in buildingSelect
        on new { b.Name, b.Status } equals new { bs.Name, bs.Status }
        select b;

答案 2 :(得分:0)

你可以覆盖类本身的相等性,如果这是有道理的。

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

    var q = (from building in BuildingList
        where buildingSelect.Any(b => b.Name == building.Name 
                                      && b.Status == building.Status)
        select building).ToList();