C#集合初始化器是否支持lambda生成器,还是仅支持固定值?
答复
是,不需要在测试类中额外编写独立函数就能实现你需要的效果,现有已正式发布的C#版本完全支持,无需等待未落地的语法特性。
原写法不生效的原因
你写在集合初始化器大括号内的lambda本身只是一个Func<List<ClassC>>类型的委托实例,编译器不会自动调用它,只会默认你要把这个委托作为单个元素添加到List<ClassC>中,最终会因为类型不匹配报编译错误。
另外你示例中的list.add是笔误,C#中列表添加元素的方法是大写开头的Add。
可用实现方案
以下两种方案兼容性极强,从C# 3.0(.NET Framework 3.5)版本开始就支持,完全适配你当前混用.NET Framework 4.6.1和.NET 6的项目环境,不需要任何额外辅助类、扩展方法。
1. 立即执行lambda表达式(IIFE)
直接在赋值位置定义lambda后立刻调用,逻辑完全内联,不需要单独定义类级方法:
ClassA instanceA = new ClassA { // 直接把lambda执行后的返回值赋值给属性即可,不需要嵌套多余的集合初始化器 MyListB = ((Func<List<ClassC>>)(() => { List<ClassC> list = new List<ClassC>(); for(int i = 0; i < 10; i++) list.Add(new ClassC() {SomeProp = i}); return list; }))() };
2. LINQ生成序列(更适合测试数据场景)
如果是像示例中那样生成带规律的测试数据,可以直接用LINQ的Enumerable.Range生成序列,代码更简洁:
// 需要先引入using System.Linq;命名空间 ClassA instanceA = new ClassA { MyListB = Enumerable.Range(0, 10) .Select(i => new ClassC { SomeProp = i }) .ToList() };
关于集合展开语法的补充说明
你提到的Roslyn仓库历史功能请求,是希望在集合初始化器中支持直接展开另一个集合的元素(类似JavaScript的...展开运算符),这个特性在C# 12版本中已经随集合表达式正式落地,如果你的项目可以配置使用C# 12语言版本(VS2022支持将C# 12编译到.NET Framework 4.6.1目标框架),还可以用更简洁的写法:
// C# 12及以上可用 ClassA instanceA = new ClassA { MyListB = [.. Enumerable.Range(0, 10).Select(i => new ClassC { SomeProp = i })] };
如果你们项目的C#语言版本不统一,优先用前面两种兼容性更好的写法即可。
内容的提问来源于stack exchange,提问作者Greg Smith
相关产品推荐
相关产品推荐

