如何在C#中将含x、y属性的类列表映射为命名值元组列表?
解决CS8143:表达式树不得包含元组字面量问题
场景与需求
现有代码结构如下:
public List<(string x, string y)> strings{ get; set; } public List<MyClass> myClasses{ get; set; } public class MyClass { public string x; public string y; // 其他成员 }
需要将myClasses列表转换为带命名的元组列表,要求保留x和y的命名,能像访问类属性一样通过.x、.y访问元组值,且希望用一行代码实现,无法直接用类来创建元组列表。
尝试的代码与错误
尝试了以下写法:
strings = myClasses.Select(mc => (mc.x, mc.y)).ToList();
触发错误:
CS8143 - 表达式树不得包含元组字面量。
解决方案
方案1:先转成内存集合再转换元组
如果myClasses的数据可以全部加载到内存,先调用ToList()将其转为内存集合,后续的Select就会使用LINQ to Objects(基于委托而非表达式树),此时就能正常使用元组字面量:
strings = myClasses.ToList().Select(mc => (x: mc.x, y: mc.y)).ToList();
注:显式指定元组的x、y命名,确保元组的命名属性与预期一致。
方案2:匿名类中转(适合需保留查询在数据库端执行的场景)
如果myClasses是IQueryable(比如EF Core的DbSet),需要先在数据库端完成匿名类的投影,再转成内存集合处理元组转换:
strings = myClasses.Select(mc => new { mc.x, mc.y }) .AsEnumerable() .Select(anon => (x: anon.x, y: anon.y)) .ToList();
AsEnumerable()会将后续的查询切换为LINQ to Objects,此时即可使用元组字面量。
原因说明
当myClasses是IQueryable类型时,Select方法会被解析为表达式树(用于将查询转换为SQL等数据源可执行的指令),而C#目前不支持在表达式树中使用值元组字面量。通过ToList()或AsEnumerable()将集合转为内存中的IEnumerable后,后续操作会基于委托执行,不再受表达式树的限制,就能正常创建值元组。
内容的提问来源于stack exchange,提问作者Federico Stefini
相关产品推荐
相关产品推荐

