You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何使用.Except方法移除两列表间的指定重复项?

如何通过Except方法按OperationId匹配移除列表元素

你的问题核心在于:Except方法默认的比较逻辑不满足需求——它对于自定义引用类型(比如MyObject)默认按对象引用而非OperationId属性值判断是否相等,所以即使两个对象的OperationId相同,也会被判定为不同元素,导致Except没达到预期效果。

下面提供几种正确使用Except实现需求的方法:


方法1:为MyObject重写Equals和GetHashCode

让MyObject基于OperationId定义相等逻辑,这样Except就能正确识别出OperationId相同的元素:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var listA = new List<MyObject>{
            new() {OperationId = 123, Mode = "In-Transit", Location = "ATL"},
            new() {OperationId = 234, Mode = "Delivered", Location = "PHX"},
            new() {OperationId = 345, Mode = "Delivered", Location = "COL"}
        };
        
        var listB = new List<MyObject>{
            new() {OperationId = 123, Mode = "In-Transit", Location = "ATL"}
        };
        
        var usingExcept = listA.Except(listB);
        // 输出2,符合预期
        Console.WriteLine(usingExcept.Count());
    }
}

public class MyObject
{
    public int OperationId { get; set; }
    public string Mode { get; set; }
    public string Location { get; set; }

    // 重写Equals,基于OperationId判断相等
    public override bool Equals(object obj)
    {
        return obj is MyObject other && OperationId == other.OperationId;
    }

    // 重写GetHashCode,确保相等的对象返回相同哈希值
    public override int GetHashCode()
    {
        return HashCode.Combine(OperationId);
    }
}

方法2:使用Except的重载,传入自定义IEqualityComparer

如果不想修改MyObject的类定义,可以创建自定义比较器,让Except用该比较器判断元素是否相等:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var listA = new List<MyObject>{
            new() {OperationId = 123, Mode = "In-Transit", Location = "ATL"},
            new() {OperationId = 234, Mode = "Delivered", Location = "PHX"},
            new() {OperationId = 345, Mode = "Delivered", Location = "COL"}
        };
        
        var listB = new List<MyObject>{
            new() {OperationId = 123, Mode = "In-Transit", Location = "ATL"}
        };
        
        var usingExcept = listA.Except(listB, new MyObjectEqualityComparer());
        // 输出2,符合预期
        Console.WriteLine(usingExcept.Count());
    }
}

public class MyObject
{
    public int OperationId { get; set; }
    public string Mode { get; set; }
    public string Location { get; set; }
}

// 自定义比较器,基于OperationId比较
public class MyObjectEqualityComparer : IEqualityComparer<MyObject>
{
    public bool Equals(MyObject x, MyObject y)
    {
        if (x == null || y == null)
            return x == y;
        return x.OperationId == y.OperationId;
    }

    public int GetHashCode(MyObject obj)
    {
        return obj?.OperationId.GetHashCode() ?? 0;
    }
}

方法3:先提取OperationId集合再筛选

如果仅需基于OperationId过滤,可先获取listB的OperationId集合,再从listA中筛选出不在该集合中的元素,效果和Except一致:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var listA = new List<MyObject>{
            new() {OperationId = 123, Mode = "In-Transit", Location = "ATL"},
            new() {OperationId = 234, Mode = "Delivered", Location = "PHX"},
            new() {OperationId = 345, Mode = "Delivered", Location = "COL"}
        };
        
        var listB = new List<MyObject>{
            new() {OperationId = 123, Mode = "In-Transit", Location = "ATL"}
        };
        
        var bOperationIds = listB.Select(b => b.OperationId).ToHashSet();
        var filteredList = listA.Where(a => !bOperationIds.Contains(a.OperationId));
        // 输出2,符合预期
        Console.WriteLine(filteredList.Count());
    }
}

public class MyObject
{
    public int OperationId { get; set; }
    public string Mode { get; set; }
    public string Location { get; set; }
}

补充说明

你原来的RemoveAll能生效,是因为显式指定了用OperationId匹配判断;而Except默认没有这个逻辑,所以需要通过上述方法给Except指定基于OperationId的相等判断规则。

内容的提问来源于stack exchange,提问作者GThree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:55:42