Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带“的Linq查询筛选器”;包括「;带列表<;T>;多元_Linq_List_Contains - Fatal编程技术网

带“的Linq查询筛选器”;包括「;带列表<;T>;多元

带“的Linq查询筛选器”;包括「;带列表<;T>;多元,linq,list,contains,Linq,List,Contains,在我的示例中,我希望通过Linq查询列表,但通过包含两个元素(名称、状态)的其他列表进行过滤。 这是一个老问题的启发,我已经适应了我的问题。 (在这个答案中,它只适用于一个元素,即状态) 我尝试使用“contains”方法,但未能成功筛选我的列表 我应该得到一个只有两栋楼(二,五栋)的结果 有人知道我停在哪里了吗 谢谢 大宗报价 公共类建筑 { 公共枚举状态类型 { 打开 关闭 奇怪的 }; 公共字符串名称{get;set;} 公共状态类型状态{get;set;} } 私有静态只读列表Build

在我的示例中,我希望通过Linq查询列表,但通过包含两个元素(名称、状态)的其他列表进行过滤。 这是一个老问题的启发,我已经适应了我的问题。 (在这个答案中,它只适用于一个元素,即状态)

我尝试使用“contains”方法,但未能成功筛选我的列表

我应该得到一个只有两栋楼(二,五栋)的结果 有人知道我停在哪里了吗

谢谢

大宗报价

公共类建筑
{
公共枚举状态类型
{
打开
关闭
奇怪的
};
公共字符串名称{get;set;}
公共状态类型状态{get;set;}
}
私有静态只读列表BuildingList=新列表()
{
新建建筑(){Name=“one”,Status=Building.StatusType.open},
新建建筑(){Name=“two”,Status=Building.StatusType.closed},
new Building(){Name=“three”,Status=Building.StatusType.wird},
新建建筑(){Name=“four”,Status=Building.StatusType.open},
新建建筑(){Name=“five”,Status=Building.StatusType.closed},
new Building(){Name=“six”,Status=Building.StatusType.wird},
};
私有void GetResult()
{
var buildingSelect=新列表
{
新建建筑(){Name=“two”,Status=Building.StatusType.closed},
新建建筑(){Name=“five”,Status=Building.StatusType.closed}
};
var q=(来自BuildingList中的building)
其中buildingSelect.Contains(building.Name、building.Status)
选择building).ToList();
dataGridView1.DataSource=q;
}

你的意思是这样的

    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;

LINQ的主要问题是,您正在尝试比较两个
建筑
的相等性,LINQ只能通过它们的引用进行比较,因为
建筑
既不实现
IEquatable
也不覆盖
对象。相等

解决此问题的一种方法是根据@Wayne的答案手动指定要比较的属性是否相等

另一种方法是,如果
构建
实例意味着通过它们的值而不是它们的引用来等同,则实现
IEquatable
并重写
对象。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;
        }
    }
}
公共类建筑:IEquatable
{
公共建筑(字符串名称、状态类型状态)
{
名称=名称;
状态=状态;
}
公共枚举状态类型
{
打开
关闭
奇怪的
};
公共字符串名称{get;}
公共状态类型状态{get;}
公共静态布尔运算符==(建筑左侧、建筑右侧)
=>等于(左、右);
公共静态布尔运算符!=(建筑左侧、建筑右侧)
=>!等于(左、右);
公共覆盖布尔等于(对象对象obj)=>Equals(对象obj作为建筑);
公共布尔等于(建筑其他)
{
if(ReferenceEquals(this,other))
{
返回true;
}
if(ReferenceEquals(other,null)| | GetType()!=other.GetType())
{
返回false;
}
返回Name==other.Name&&Status==other.Status;
}
公共覆盖int GetHashCode()
{
未经检查
{
int hash=17;
hash=hash*23+Name?.GetHashCode()??0;
hash=hash*23+Status.GetHashCode();
返回散列;
}
}
}

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

如果有意义,您可以覆盖类本身中的相等性

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

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

我只剩下一个问题,因为我需要通过删除一些行来修改buildingSelect列表,如下所示:“code buildingSelect.Remove(new Building(){Name=“two”,Status=Building.StatusType.closed};”这不管用。有没有办法纠正这个问题。您好,请参阅rexcfnghk的回答<代码>列表。如果您的
Building
对象未实现
GetHashCode
Equals
,则Remove将使用引用相等,因此您的
新建筑将永远不存在于
buildingSelect
集合中,并且根据定义无法删除。感谢rexcfnghk,通过这一点,我学习并试验了IEquatable实现。Contains现在正在对我的原始代码>“where buildingSelect.Contains(new Building(Building.Name,Building.Status))”进行一些细微的更新。在列表中删除也可以。伟大的非常感谢。如果我的回答帮助了你,请考虑接受它作为回答。
    var q = (from building in BuildingList
        where buildingSelect.Any(b => b.Name == building.Name 
                                      && b.Status == building.Status)
        select building).ToList();