C# 12集合表达式触发CS9172错误:为何编译器无法推断类型?
C# 12集合表达式无法直接调用LINQ方法的技术原因
当你尝试用C# 12的集合表达式写这样的代码时:
if (["blue", "red", "foo"].Any((x) => { // 逻辑代码 }))
会触发CS9172编译错误:“集合表达式没有目标类型”,必须改用C# 12之前的new[] { "blue", "red", "foo" }写法才行。明明所有元素都是同类型,编译器为啥做不到类型推断?核心原因在于集合表达式的设计逻辑:
- 集合表达式本身是无默认类型的语法糖,它的类型完全依赖上下文的“目标类型”推导。比如赋值给
var list = ["a","b"];会默认转成List<string>,赋值给string[] arr = ["a","b"];会转成数组,但它不会像new[]那样自动锁定为某一种集合类型。 - LINQ的
Any是扩展方法,调用扩展方法必须先确定调用者的具体类型。Any的扩展目标是IEnumerable<T>,但这是个抽象接口,无数集合类型都实现了它——编译器没办法从Any的签名反向推断出要把集合表达式转换成哪种具体类型(数组?List?还是自定义集合?),因此只能报错要求明确目标类型。 - 而
new[] { ... }是专门的数组创建表达式,编译器会直接根据元素类型推断出T[](这里就是string[]),数组本身实现了IEnumerable<T>,所以能直接被Any识别调用。
如果要让集合表达式直接支持这种写法,需要编译器新增逻辑:当集合表达式作为扩展方法调用者时默认推断为数组类型。但这会打破集合表达式“无默认类型、依赖目标上下文”的设计原则,可能引发类型推断歧义(比如存在多个针对不同集合类型的扩展方法时,编译器该选择哪种转换?),所以目前C#团队没有做这个设计。
内容的提问来源于stack exchange,提问作者rory.ap
相关产品推荐
相关产品推荐

