c# list 去重的方法

发布时间 - 2025-12-27 00:00:00    点击率:
Distinct()去重需确保类型正确实现Equals和GetHashCode;值类型和已重载的引用类型(如string)可直接使用,自定义类必须重写二者;.NET6+推荐DistinctBy()按属性去重;原地去重宜用HashSet配合RemoveAll;忽略大小写需传StringComparer。

Distinct() 去重最常用,但要注意类型是否实现 EqualsGetHashCode

对值类型(如 intstring)或已重写相等逻辑的引用类型,直接调用 Linq.Distinct() 即可。它底层依赖对象的相等比较机制:

  • 没重写时,引用类型默认按内存地址判等,即使内容相同也会保留多份
  • string 是特例,虽是引用类型但已重载,所以 new List { "a", "a" }.Distinct() 能正确去重
  • 自定义类必须重写 Equals(object)GetHashCode(),否则 Distinct() 无效
var numbers = new List { 1, 2, 2, 3 };
var unique = numbers.Distinct().ToList(); // [1, 2, 3]

按指定属性去重要用 DistinctBy()(.NET 6+)或自定义 IEqualityComparer

常见需求是“按 IdName 去重”,Distinct() 本身不支持投影。.NET 6 引入了 DistinctBy(),简洁安全:

  • DistinctBy(x => x.Id) 会保留第一个出现的 Id 对应项,后续同 Id 的跳过
  • 低版本需手写 IEqualityComparer,容易漏掉 GetHashCode 实现,导致哈希表行为异常
  • 避免用 GroupBy(x => x.Id).Select(g => g.First()) —— 性能差,且语义不如 DistinctBy 清晰
var users = new List {
    new User { Id = 1, Name = "Alice" },
    new User { Id = 1, Name = "Bob" },
    new User { Id = 2, Name = "Charlie" }
};
var uniqueById = users.DistinctBy(u => u.Id).ToList(); // 保留 Id=1 的第一个(Alice)

原地去重用 HashSet 配合 RemoveAll() 或重建列表

Distinct() 返回新集合,若需修改原 List,不能直接赋值(会丢失引用)。稳妥做法是清空后重新填充:

  • HashSet 判断重复最高效(O(1) 查找),比嵌套循环或 Contains 快得多
  • 对引用类型,仍要确保 T 的相等逻辑正确,否则 HashSet 也失效
  • 别用 for 循环边遍历边删 —— 容易跳过元素或索引越界
var list = new List { "x", "y", "x", "z" };
var seen = new HashSet();
list.RemoveAll(item => !seen.Add(item)); // seen.Add 返回 true 表示首次加入

字符串忽略大小写的去重必须传 StringComparer

Distinct() 默认区分大小写,"A""a" 被视为不同。强行转小写再比较(如 Select(x => x.ToLower()).Distinct())会丢失原始大小写形式:

  • Distinct(StringComparer.OrdinalIgnoreCase) 既去重又保留原字符串
  • StringComparer.CurrentCultureIgnoreCase 更适合本地化场景,但性能略低
  • 别在 DistinctBy 里用 x.Name.ToLower() 做 key —— 同样丢失原始值,且无法处理 null
var words = new List { "Apple", "apple", "Banana", "BANANA" };
var unique = words.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); // ["Apple", "Banana"]
实际用哪一种,取决于你手上的数据类型、.NET 版本、是否需要保留原列表引用,以及“重复”的定义粒度——是整个对象相等,还是某个字段一致。最容易被忽略的是自定义类没重写 GetHashCode,结果 Distinct()HashSet 表现诡异,调试时得回头检查这一条。


# word  # app  # ai  # apple  # 本地化  # c#  # .net  # 数据类型  # String  # Object  # NULL  # for  # select  # 字符串  # int  # 循环  # 值类型  # 引用类型  # 对象  # linq  # 重写  # 自定义  # 第一个  # 跳过  # 的是  # 这一  # 也会  # 首次  # 遍历  # 要用 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在宝塔面板中修改默认建站目录?  Laravel如何创建自定义Facades?(详细步骤)  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  如何用PHP工具快速搭建高效网站?  网站制作软件有哪些,制图软件有哪些?  linux写shell需要注意的问题(必看)  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  JavaScript如何实现错误处理_try...catch如何捕获异常?  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  轻松掌握MySQL函数中的last_insert_id()  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  如何快速辨别茅台真假?关键步骤解析  Laravel如何处理表单验证?(Requests代码示例)  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  如何快速搭建高效香港服务器网站?  北京网站制作公司哪家好一点,北京租房网站有哪些?  详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  Android利用动画实现背景逐渐变暗  如何用腾讯建站主机快速创建免费网站?  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  如何破解联通资金短缺导致的基站建设难题?  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】  Laravel如何自定义错误页面(404, 500)?(代码示例)  如何快速使用云服务器搭建个人网站?  php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】  手机网站制作与建设方案,手机网站如何建设?  ,网页ppt怎么弄成自己的ppt?  宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  非常酷的网站设计制作软件,酷培ai教育官方网站?  浅谈javascript alert和confirm的美化  如何在企业微信快速生成手机电脑官网?  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Laravel怎么判断请求类型_Laravel Request isMethod用法  微信小程序 scroll-view组件实现列表页实例代码  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  Laravel如何实现事件和监听器?(Event & Listener实战)  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  Firefox Developer Edition开发者版本入口  google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  制作电商网页,电商供应链怎么做?