为何C#中传入dynamic项到方法后,编译器不验证返回类型兼容性?
C#中dynamic循环场景下的编译器类型检查问题
在C#中,当遍历返回dynamic类型元素的循环时,将dynamic元素传入方法后,把方法返回值赋值给不兼容类型的变量,编译器不会对方法的返回类型进行验证。
注意:有一个类似问题,但该问题核心是返回类型变更,本文聚焦的是编译器类型检查行为,这是两者的关键区别。
以下示例能更清晰地说明问题:为何编译器不抛出类型转换错误?
void Main() { List<dynamic> vals = new List<dynamic>(100); for (int i = 0; i < 100; i++) vals.Add(new { Id = i}); foreach (dynamic itm in vals) { //无编译错误,为何?GetId应返回int类型! string result = GetId(itm); Console.WriteLine($"id: {result}"); } //id2必须为int类型,否则会出现编译错误 int id2 = GetId(new {Id = 100}); } public static int GetId(dynamic b) { return b.Id; }
上述代码可正常编译,但运行时会触发错误,该运行时错误符合预期。
错误信息:
HResult: -2146233088
InnerException: null
Message: 无法将类型“int”隐式转换为“string”
原因解析
这是因为当方法的参数为dynamic类型时,整个方法调用会被标记为动态绑定操作,编译器会将所有类型检查逻辑推迟到运行时执行:
- 在遍历
dynamic元素的循环中,调用GetId(itm)时,由于itm是dynamic类型,编译器不会解析GetId的静态返回类型(int),而是在运行时才会确定方法调用的实际返回类型,并尝试执行隐式转换。因此编译阶段不会检测到int转string的不兼容问题。 - 而在
int id2 = GetId(new {Id = 100})的代码中,传入的是匿名类型(非dynamic),编译器会执行静态类型检查,明确GetId的返回值为int,所以如果将右边赋值给string类型变量,编译阶段就会直接报错。
内容的提问来源于stack exchange,提问作者Rax
相关产品推荐
相关产品推荐

