我想通过Linq查询列表,但是在我的示例中使用包含两个元素(Name,Status)的其他列表进行过滤。 这是受到我已经适应我的问题的一个老问题的启发。 LINQ: "contains" and a Lambda query (在这个答案中,它仅适用于一个元素,即状态)
我尝试使用" contains"方法,但没有成功过滤我的列表。
我应该只用两栋建筑物(两个,五个)获得一个结果 有没有人知道我在哪里停下来?
谢谢
块引用
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;
}
答案 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();