c# - 比较两个自定义 LIST 对象

标签 c# linq lambda

我有场景要检查

1) 如果 empDb 中的任何属性 (EmployeeObject) 出现在 empXml 中,则返回 true。否则返回 false

public class EmployeeObject
{
    public Int32 Id { get; set; }
    public string Title { get; set; }
    public string Desc { get; set; }
    .....
}

IList<EmployeeObject> empDb  = PopulateFromDb(); //calling ado.net
IList<EmployeeObject> empXml = PopulateFromXml(); //deserializing xml

让我直截了本地说,我正在尝试确定列表 empXml 是否是列表 empDb 的子集?

到目前为止已经尝试过;但即使我已经检查了两个列表中的数据,它也返回 false,它应该返回 true,除非我在我的表达式中做错了什么。

//at least one MATCH
empDb.Any(a => empXml.Contains(a));

//at least one EXACT match
empDb.Any(x => empXml.Contains(y => x.Equals(y)));

最佳答案

如果您没有在 EmployeeObject 类中实现 EqualsGetHashCode,那么员工将通过引用进行比较。你肯定会在这里有不同的实例,因为第一个列表是在你从数据库中读取数据时创建的,而第二个列表是在你反序列化 xml 时创建的。因此,即使是在所有领域具有相同值(value)观的员工也会被认为是不同的。

如果您只想通过员工 ID 检查匹配项,那么您可以将序列投影到 ID,然后使用 Intersect检查匹配是否存在

// at least one employee with equal Id
empDb.Select(e => e.Id).Intersect(empXml.Select(e => e.Id)).Any()

如果您想按员工字段的值而不是他们的引用来比较员工,您有多种选择。如果您不能或不想更改 EmployeeObject 类的实现并覆盖其 Equals 和 GetHashCode 方法,那么您可以为员工创建自定义的比较器:

public class EmployeeComparer : IEqualityComparer<EmployeeObject>
{
    public bool Equals(EmployeeObject x, EmployeeObject y)
    {
        return x.Id == y.Id
            && x.Title == y.Title
            && x.Desc == y.Desc;
    }

    public int GetHashCode(EmployeeObject obj)
    {
        int code = 19;
        code = code * 23 + obj.Id.GetHashCode();
        code = code * 23 + obj.Title.GetHashCode();
        code = code * 23 + obj.Desc.GetHashCode();
        return code;
    }
}

然后你可以使用这个比较器:

empDb.Intersect(empXml, new EmployeeComparer()).Any()

或者您可以将您的员工转换到匿名对象(默认实现了 Equals 和 GetHashCode):

empDb.Select(e => new { e.Id, e.Title, e.Desc })
     .Intersect(empXml.Select(e => new { e.Id, e.Title, e.Desc })).Any()

或者覆盖这些方法:

public class EmployeeObject
{
    public Int32 Id { get; set; }
    public string Title { get; set; }
    public string Desc { get; set; }

    public override int GetHashCode()
    {
        int code = 19;
        code = code * 23 + Id.GetHashCode();
        code = code * 23 + Title.GetHashCode();
        code = code * 23 + Desc.GetHashCode();
        return code;
    }

    public override bool Equals(object obj)
    {
        EmployeeObject other = obj as EmployeeObject;
        if (other == null)
            return false;

        if (ReferenceEquals(this, other))
            return true;

        return Id == other.Id && 
               Title == other.Title && Desc == other.Desc;                 
    }
}

您的代码将起作用。或者您可以使用相交:

empDb.Intersect(empXml).Any()

关于c# - 比较两个自定义 LIST 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21556338/

相关文章:

c# - 将数据类型 'long' 转换为字节数组

c# - 从异步方法返回部分结果

c# - 扩展 IQueryable 查询的属性

c# - 使用 LINQ 在 C# 中将值和范围绑定(bind)到下拉列表

与 Selenium2 ExpectedCondition 一起使用 Lambda 表达式?

amazon-web-services - 错误 : exec: \"app.handler\": executable file not found in $PATH", "errorType": "Runtime.InvalidEntrypoint"

c# - 模拟 DbSet<T> 内联

c# - 将一个点向另一个点移动一定的距离

c# - 如何使用linq过滤类列表中的列表?

vb.net - 如何在 vb.net 中使用 lambda 删除列表的指定项目