问题情景#
订单页面需要展示不同订单的游客信息,订单信息有一个公共数据实体,而游客有不同的两个不同的数据实体,于是就有了类似下面的代码
public class Order
{
public string SerialId = string.Empty;
public dynamic Tours = null;
}
var order = new Order();
order.Tours = new List<string>();
order.Tours.Any();
赋值后在前台将Tours as 成我们想要的游客数据实体列表,然后在判断是否存在数据时 order.Tours.Any()
报错:“System.Collections.Generic.List<string>”未包含“Any”的定义
问题分析#
首先我们得到的确实是一个List类型,那么问题就出现在.Any()
这个LINQ语句中,原因是“动态对象不支持扩展方法。lambda也不能用作动态方法调用的参数,因此LINQ不能用于动态对象。大多数LINQ调用都是扩展方法。”-C#高级编程
这是why,那么why why?
public class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
//dynamic list = new List<string>();
list.Any();
}
}
Paste_Image.png
Paste_Image.png
看上面的代码和截图,代码编译成IL后执行过程就已经明确下来,执行需要信息完备了。但是dynamic类型编译成的IL却并没有明确这些执行信息,而是在执行IL时去查找操作的类型,生成表达式树来绑定需要的操作。
重要的事情来了,dynamic类型生成的IL是动态去查找类型绑定方法,然而扩展方法并不是定义在目标类型中,而只是外部的一个扩展。这时候我们自然就无法找到需要调用的方法,也就会抛出出现开头的报错信息。
解决方案#
- 如果目标类型确定的话,将dynamic类型强制转换成需要的类型赋值给一个中间变量,然后操作中间变量。
- 试着使用
List<dynamic>
来接收数据
扩展延伸#
- 从上面的示例我们可以知道dynamic类型生成的IL远比一般代码要多得多,所以对性能的影响肯定是有的,建议非特殊情况下能不用dynamic类型就不用。
就比如本人上面的代码。 - 对于IL等一些比较底层的东西,也许日常工作中不需要了解,但是能了解一些绝对是有帮助的。
网友评论