游乐游手机版
首页/编程语言/文章详情

c#如何实现自定义集合_c#自定义集合项目实例附完整源码

时间:2026-04-15 08:21
C 自定义集合开发指南:为何应优先继承Collection而非手动实现接口 在C 开发中,创建自定义集合类是一个常见需求。本文将深入探讨一个高效且安全的实现方案:优先继承Collection基类,而非手动实现IEnumerable或IList接口。这一选择能显著提升开发效率,确保数据绑定兼容性,并降

C#自定义集合开发指南:为何应优先继承Collection而非手动实现接口

c#如何实现自定义集合_c#自定义集合项目实例附完整源码

在C#开发中,创建自定义集合类是一个常见需求。本文将深入探讨一个高效且安全的实现方案:优先继承Collection基类,而非手动实现IEnumerableIList接口。这一选择能显著提升开发效率,确保数据绑定兼容性,并降低代码维护成本。

避免直接实现IEnumerable的三大理由

许多开发者初次尝试创建自定义集合时,会从实现IEnumerable接口开始。然而,这种方法存在几个根本性缺陷:

首先,IEnumerable仅定义了枚举遍历能力,不包含任何集合修改功能。这意味着您需要额外实现AddRemoveCount等核心成员,工作量远超预期。

其次,LINQ扩展方法(如WhereSelect)会返回新的IEnumerable实例,导致自定义集合的业务规则(如数据验证)在链式调用中丢失。

  • IEnumerable本质上是只读遍历协议,不提供集合修改能力
  • 手动实现完整IList需要重写超过20个成员,极易遗漏关键方法
  • WPF/WinForms数据绑定机制依赖INotifyCollectionChanged接口,仅实现IEnumerable会导致UI无法自动更新

利用Collection基类快速构建业务集合

Collection是.NET框架专门为自定义集合开发设计的可扩展基类。其核心优势在于:

它将所有集合操作拆分为独立的可重写虚方法:InsertItemRemoveItemSetItemClearItems。开发者只需重写需要添加业务逻辑的方法,其余功能由基类自动处理。

以下示例展示如何创建“仅接受正整数”的自定义集合:

public class PositiveIntCollection : Collection
{
    protected override void InsertItem(int index, int item)
    {
        if (item <= 0) throw new ArgumentException("只允许添加正整数");
        base.InsertItem(index, item);
    }
protected override void SetItem(int index, int item)
{
    if (item <= 0) throw new ArgumentException("只允许设置正整数");
    base.SetItem(index, item);
}

}

  • 自动获得完整的枚举器实现,支持foreach遍历和所有LINQ操作
  • 所有修改入口(Add、Insert、索引器赋值)均被统一拦截,确保业务规则一致性
  • 可轻松扩展集合变更通知机制,支持日志记录或UI自动刷新

手动实现IList的适用场景与风险

虽然继承基类是最佳实践,但在特定场景下仍需手动实现接口:

1. 性能关键型数据结构:如固定大小的环形缓冲区、内存池等需要极致性能的场景

2. 特殊内存布局需求:如将集合直接映射到非托管内存或特定数组结构

一个常见误区是试图通过IList实现“智能过滤”集合。例如,创建自动跳过null元素的列表会遇到语义矛盾:Count属性应返回总长度还是非空元素数?索引器this[0]应返回第一个元素还是第一个非空元素?

  • IList契约要求Count属性必须为O(1)时间复杂度
  • 索引器必须直接访问物理位置元素,不能动态过滤后重新编排索引
  • 过滤需求应使用LINQ的Where方法,而非修改集合基础语义

完整实战示例:带唯一性约束的排序集合

以下是一个可直接使用的C#自定义集合实现,兼具元素唯一性和自动排序功能:

public class SortedUniqueIntCollection : Collection
{
    private readonly SortedSet _inner = new();
public override int Count => _inner.Count;
protected override void InsertItem(int index, int item)
{
    if (_inner.Add(item)) base.InsertItem(index, item);
    else throw new InvalidOperationException($"重复值 {item} 不允许插入");
}
protected override void RemoveItem(int index)
{
    _inner.Remove(this[index]);
    base.RemoveItem(index);
}
protected override void ClearItems() {
    _inner.Clear();
    base.ClearItems();
}

}

重要说明:此实现使用SortedSet辅助集合来维护唯一性和快速查找,但实际数据存储仍在基类的Items属性(List类型)中。因此,foreach遍历顺序为插入顺序,而非排序顺序。

若需要严格按排序顺序遍历,建议封装SortedSet并实现IEnumerableIReadOnlyList接口。这一设计决策对集合行为有重要影响,应在项目初期明确需求。

来源:https://www.php.cn/faq/2316950.html
上一篇如何优雅处理 JSON 中字段类型不一致(时而对象、时而数组)的问题 下一篇如何在 Go 语言中按指定间隔向字符串插入字符
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CentOS与Golang打包常见兼容性问题探讨
编程语言 · 2026-07-01

CentOS与Golang打包常见兼容性问题探讨

CentOS与Golang打包的兼容性问题集中在glibc版本不匹配、交叉编译环境变量错误、依赖库缺失及Go依赖管理不规范。可通过Docker容器编译、选择兼容Go版本、正确设置GOOS GOARCH环境变量、安装对应开发包及使用GoModules解决。

CentOS中Fortran与Python如何协同工作从入门到实战完整教程
编程语言 · 2026-07-01

CentOS中Fortran与Python如何协同工作从入门到实战完整教程

在CentOS中,Fortran与Python可通过f2py、SWIG、共享库调用或subprocess协同。f2py封装Fortran为Python模块,支持数组运算;共享库需手动对齐数据类型;系统调用适合独立计算。

CentOS中Golang打包优化方法
编程语言 · 2026-07-01

CentOS中Golang打包优化方法

在CentOS中优化Golang编译打包,可显著提升编译速度并减小二进制文件体积。关键技巧包括:设置环境变量、使用Go模块管理依赖、编译时添加-ldflags= "-s-w "去除调试信息、利用UPX工具压缩、运行strip清理符号表,以及优化cgo内C代码的编译选项。综合运用这些方法能有效优化最终程序。

在CentOS系统中cpustat与其他工具协同使用的完整方法
编程语言 · 2026-07-01

在CentOS系统中cpustat与其他工具协同使用的完整方法

cpustat作为sysstat包的CPU监控工具,可通过管道与grep等命令配合过滤数据,利用脚本自动记录带时间戳的日志,或结合图形工具查看,也可格式化输出后接入Zabbix、Grafana等Web监控系统,实现可视化与告警。

CentOS中readdir与其他Linux发行版的差异
编程语言 · 2026-07-01

CentOS中readdir与其他Linux发行版的差异

CentOS基于RHEL,与Ubuntu、Debian、Fedora在包管理器(yum dnfvsapt)、默认文件系统(XFSvsext4)等存在差异,但readdir等系统调用遵循POSIX标准,行为一致。