.NET投影与dynamic返回类型不匹配问题咨询
问题描述
我编写了如下异步方法:
public async Task<List<dynamic>> GetIdsOfPersoane() { return await GetRecords(true).Select(p => new {p.Id, p.Nume}).ToListAsync(); }
其中GetRecords方法用于从数据库获取数据。我希望使用投影操作,但不想为此方法单独创建新对象,尝试返回dynamic类型以避免装箱拆箱,却出现如下错误:
Cannot convert expression type 'System.Collections.Generic.List<{int Id, string Nume}>' to return type 'System.Collections.Generic.List<dynamic>
请问该错误产生的原因是什么?dynamic类型为何无法按此方式使用?
错误原因与解决思路
错误原因
泛型集合的协变限制:
List<T>是不可协变的泛型类型。虽然单个匿名类型实例可以隐式转换为dynamic,但List<匿名类型>和List<dynamic>是两种完全独立的封闭构造类型,C#编译器不允许直接进行这种跨类型的隐式转换。dynamic的编译期特性:dynamic只是编译阶段的类型标识,运行时它的实际类型仍是那个匿名类型。但泛型集合的类型兼容性检查在编译期完成,编译器无法确认List<匿名类型>可以安全转换为List<dynamic>——只有标记了out关键字的泛型接口(比如IEnumerable<out T>)才支持协变,List<T>并不具备这个特性。
解决方法
如果要返回List<dynamic>,可以通过以下两种方式实现:
- 方式一:使用
Cast<dynamic>显式转换每个元素
public async Task<List<dynamic>> GetIdsOfPersoane() { return await GetRecords(true) .Select(p => new {p.Id, p.Nume}) .Cast<dynamic>() .ToListAsync(); }
- 方式二:利用
IEnumerable<dynamic>的协变性中转
public async Task<List<dynamic>> GetIdsOfPersoane() { IEnumerable<dynamic> temp = await GetRecords(true) .Select(p => new {p.Id, p.Nume}) .ToListAsync(); return temp.ToList(); }
内容的提问来源于stack exchange,提问作者Octavian Niculescu
相关产品推荐
相关产品推荐

