C#除了业务查询和数据获取,IEnumerable还有其他高频使用场景

这里补充业务查询/数据获取之外的高频场景,覆盖 UI、配置、工具、集合操作、框架扩展、校验、转换等方向,附代码示例,都是实际项目中频繁用到的场景。

一、UI 界面数据绑定(桌面/前端框架高频)

场景说明

WinForm、WPF、ASP.NET、Blazor 等 UI 框架中,控件列表数据源普遍接收 IEnumerable<T>,是界面展示的核心载体。

  • 优势:适配所有集合类型,框架内部自动遍历渲染。

1. WinForm DataGridView / ComboBox 绑定

// 模拟数据
var data = new List<string> { "选项1", "选项2", "选项3" };
IEnumerable<string> bindData = data;

// 下拉框绑定
comboBox1.DataSource = bindData;

// 表格绑定
dataGridView1.DataSource = bindData.ToList();

2. WPF 列表控件(ListBox/ItemsControl)

XAML 控件的 ItemsSource 类型本身就是 IEnumerable

<ListBox ItemsSource="{Binding UserList}" />

后端属性定义:

private IEnumerable<User> _userList;
public IEnumerable<User> UserList
{
    get => _userList;
    set { _userList = value; OnPropertyChanged(); }
}

二、集合合并、去重、拼接、过滤(通用工具逻辑)

日常对多个序列做组合处理,IEnumerable 配合 LINQ 是标准写法,不属于数据库查询,纯内存运算。

1. 多个序列合并

IEnumerable<int> seq1 = new[] { 1, 2, 3 };
IEnumerable<int> seq2 = new[] { 3, 4, 5 };

// 拼接两个序列
var all = seq1.Concat(seq2);
// 合并并去重
var distinctAll = seq1.Union(seq2);

2. 批量过滤、排除元素

// 排除指定黑名单数据
IEnumerable<string> allTags = new[] { "标签A", "标签B", "标签C" };
IEnumerable<string> blackList = new[] { "标签B" };

var validTags = allTags.Except(blackList);

3. 交集、差集、子集判断(数据比对)

常用于权限、标签、角色、配置项比对:

// 用户拥有的角色
IEnumerable<string> userRoles = new[] { "管理员", "编辑" };
// 接口要求的权限
IEnumerable<string> requireRoles = new[] { "管理员" };

// 判断是否拥有权限(是否存在交集)
bool hasPermission = userRoles.Intersect(requireRoles).Any();

三、批量操作:循环执行任务/调用方法

批量执行逻辑、批量校验、批量下发指令、批量日志输出,用 IEnumerable 承载待处理对象。

1. 批量执行动作

// 待处理任务序列
IEnumerable<TaskItem> tasks = GetLocalTasks();

// 批量执行
foreach (var task in tasks)
{
    task.Run();
}

2. 批量参数校验

/// <summary>批量校验字符串非空</summary>
public static bool AllNotEmpty(IEnumerable<string> inputs)
{
    return inputs.All(s => !string.IsNullOrWhiteSpace(s));
}

// 调用
var checkItems = new[] { "测试1", "", "测试2" };
bool result = AllNotEmpty(checkItems);

四、配置项、枚举、常量遍历

系统配置、字典映射、枚举遍历、静态常量集合,大量使用 IEnumerable 封装。

1. 枚举遍历

enum Status { 正常, 禁用, 注销 }

// 获取所有枚举项,返回 IEnumerable
IEnumerable<Status> allStatus = Enum.GetValues(typeof(Status)).Cast<Status>();

foreach (var s in allStatus)
{
    Console.WriteLine(s);
}

2. 系统配置字典/选项集

// 系统预设选项,只读对外暴露
public static IEnumerable<KeyValuePair<string, string>> SystemOptions
{
    get
    {
        yield return new KeyValuePair<string, string>("0", "关闭");
        yield return new KeyValuePair<string, string>("1", "开启");
    }
}

五、分页、分片、分批处理(内存数据分页)

不依赖数据库,纯内存集合分页/分片,报表导出、数据分批推送、分块处理都在用。

// 原始序列
IEnumerable<LogInfo> allLogs = GetAllLog();
int pageSize = 20;

// 内存分页
var page1 = allLogs.Skip(0).Take(pageSize);
var page2 = allLogs.Skip(pageSize).Take(pageSize);

大数据分片处理(避免单次处理过多数据)

// 将序列按每 50 条分为一批
var batches = allLogs.Select((item, index) => new { item, index })
                     .GroupBy(x => x.index / 50)
                     .Select(g => g.Select(x => x.item));

foreach (var batch in batches)
{
    // 分批处理,降低单次压力
    ProcessBatchData(batch);
}

六、字符串、文本拆分与遍历

字符串分割、逐字符/逐片段遍历,结合 IEnumerable 做流式处理。

1. 字符遍历

string content = "Hello World";
IEnumerable<char> chars = content; // string 本身实现了 IEnumerable<char>

foreach (var c in chars)
{
    Console.Write(c);
}

2. 拆分字符串并过滤

string str = "1,2,,3,4";
IEnumerable<string> parts = str.Split(',')
                                .Where(s => !string.IsNullOrEmpty(s));

七、日志、监控、事件回调(事件集合/订阅列表)

事件订阅、钩子函数、日志处理器、监控触发器,用 IEnumerable 管理一组回调对象。

// 日志处理器列表
private readonly List<ILogHandler> _logHandlers = new List<ILogHandler>();

// 对外只读暴露处理器
public IEnumerable<ILogHandler> LogHandlers => _logHandlers;

// 触发所有日志处理器
public void WriteLog(string msg)
{
    foreach (var handler in LogHandlers)
    {
        handler.Handle(msg);
    }
}

八、参数设计:统一接收多类型入参(通用工具类)

公共工具、扩展方法、帮助类,参数统一声明为 IEnumerable<T>,兼容数组、List、HashSet、LINQ 结果等所有可遍历类型,提升复用性。

示例:通用扩展方法

public static class EnumerableExt
{
    // 任意可遍历集合都能调用
    public static string JoinToString<T>(this IEnumerable<T> source, string separator = ",")
    {
        return string.Join(separator, source);
    }
}

// 各种类型都能调用
int[] arr = { 1, 2, 3 };
List<int> list = { 4, 5 };

string s1 = arr.JoinToString();
string s2 = list.JoinToString("|");

九、缓存与内存数据管理

缓存列表、内存常驻数据池、临时会话数据,对外用 IEnumerable 保证只读,防止外部篡改缓存。

// 全局内存缓存
private static readonly List<DictItem> _dictCache = new List<DictItem>();

// 只读对外暴露,保护缓存数据
public static IEnumerable<DictItem> DictCache => _dictCache;

十、异步流 / 管道处理(进阶:IAsyncEnumerable)

现代 .NET 中衍生的 IAsyncEnumerable<T>,基于迭代思想,用于异步流式读取

  • 异步读取网络流、消息队列、实时日志、推送数据流
  • EF Core 异步分页查询、大文件异步读取
// 异步逐行读取文件
public static async IAsyncEnumerable<string> ReadFileAsync(string path)
{
    using var reader = new StreamReader(path);
    string line;
    while ((line = await reader.ReadLineAsync()) != null)
    {
        yield return line;
    }
    // 遍历过程中异步等待,不阻塞线程
    await Task.Yield();
    }
}

场景汇总&优先级(非数据查询类)

场景分类 使用频率 典型用途
UI 控件数据源绑定 ★★★★★ WinForm/WPF/Blazor 列表渲染
集合运算(合并/去重/交集) ★★★★★ 内存数据比对、组合、筛选
批量执行/批量校验 ★★★★☆ 任务批量执行、参数校验、指令下发
枚举/配置项遍历 ★★★★☆ 系统下拉选项、枚举解析、静态配置
内存分页/分片处理 ★★★★☆ 报表、分批导出、分块计算
字符串拆分与遍历 ★★★☆☆ 文本解析、字符处理
事件/回调/处理器集合 ★★★☆☆ 日志、钩子、事件订阅
通用工具方法入参 ★★★★★ 公共扩展方法、帮助类
内存缓存只读暴露 ★★★☆☆ 全局字典、常驻数据
异步流式处理 ★★★☆☆ 消息队列、大文件异步读写

补充小结

  1. IEnumerable 本质是「序列抽象」,不局限于数据库/业务查询,只要是“一组有序元素”,基本都能用它;
  2. 日常编码中:UI绑定、集合运算、批量操作、工具方法 是除数据查询外,最高频的四大场景;
  3. 设计原则:只要只需要遍历、只读、兼容多容器,就优先选用 IEnumerable<T>
posted @ 2026-06-10 06:04  人生就是修炼  阅读(6)  评论(0)    收藏  举报