【发布时间】:2017-10-25 23:20:00
【问题描述】:
我已经调试这个问题几个小时,终于找到了问题的罪魁祸首。让我解释一下设置。
(我有这些接口和实现它们 A、B 的类)
public interface IA { public void DoSomething(int i); }
public interface IB : IA { public void SomethingElse(); }
(在某个类的某个方法中)
dynamic options = JSonConvert.DeserializeObject<dynamic>(json);
var id = int.Parse(options.someId.ToString());
IB b = new B();
b.DoSomething(id);
此代码按预期编译,但在运行时我得到“IB 不包含 'DoSomething' 的定义”。
但是,如果我改为:
var id = 1;
IB b = new B();
b.DoSomething(id);
然后一切正常!
以前我在方法中使用动态时也发生过类似的事情。这里发生了什么?有人知道吗?
注意:我可以通过将两条线移到不同的方法来轻松避免这种情况,或者完全避免使用动态,但我只是好奇为什么:)
有趣的事实:当我在一个接口和一个类中包含“DoSomething”和“SomethingElse”时,这并没有造成任何问题......
【问题讨论】:
-
动态传染。
id是动态的,因此编译器拒绝对其进入的任何方法返回的任何内容做出任何假设。一切都被视为动态的,并且规则不同。试试int id = (int)options.someId;或其他什么,看看会发生什么。 -
你能显示为真实代码吗?考虑准备mcve。
-
@DiskJunky 当涉及
dynamic时,在运行时进行重载解析。编译器不知道实际会调用什么方法。很可能是爷爷的老熟人int.Parse(),但“很可能”并不合适。 -
您可以通过将鼠标悬停在
var上来验证所有这些。使用dynamic时永远不要假设类型,因为你实际上是在扔掉打字系统。 -
@AndersLindas 正常调用
int.Parse();没有超载的。问题在于,对于dynamic,编译器假定可能存在,所以它只是说“废话,这都是动态的,无论如何”——那么b就是dynamic,它意味着它在运行时解析方法调用,并且运行时方法解析忽略基类或其他东西,我不记得确切的细节。但这就是失败的地方:在运行时解析方法的工作方式不同,它在运行时解析DoSomething(),因为上游有一个dynamic。
标签: c# dynamic runtime-error