当我运行以下代码时,我得到RuntimeBinderException: 'object' does not contain a definition for 'SetIt'
。
public interface IInput { }
public interface IThing<in TInput>
{
void SetIt(TInput value);
}
public class ThingMaker
{
private class Thing<TInput> : IThing<TInput>
where TInput : IInput
{
public void SetIt(TInput value){}
}
private class Input : IInput {}
public IThing<IInput> GetThing()
{
return new Thing<IInput>();
}
public IInput GetInput()
{
return new Input();
}
}
class Program
{
static void Main(string[] args)
{
var thingMaker = new ThingMaker();
var input = thingMaker.GetInput();
dynamic thing= thingMaker.GetThing();
thing.SetIt(input);
}
}
如果我将thing
切换为var
,则可以正常使用。很明显,thing
有SetIt
。当我使用动态时,怎么会失败呢?任何适用于var
的内容都不应该在dynamic
时起作用吗?
我认为它与Thing<TInput>
是一个私有的内部类有关,因为它在我公开时会起作用。
答案 0 :(得分:1)
以下是您问题的简单示例:
class A
{
class B
{
public void M() { }
}
public static object GetB() { return new B(); }
}
class Program
{
static void Main(string[] args)
{
dynamic o = A.GetB();
o.M();
}
}
泛型和界面只是一种分心。
问题是类型B
(或者在您的情况下,Thing<IInput>
)是私有类,因此在调用站点,无法解析为该实际类型。回想一下,dynamic
只是一个object
变量,但编译推迟到运行时。它不是为了让你在运行时做你无法做到的事情,并且“根本无法做到”是根据呼叫站点的可访问类型来判断的(在此case,是object
)。
就运行时绑定程序而言,类型只是object
(因此错误消息告诉您object
不包含您想要的成员。)
当然,理论上可能dynamic
可以以不同的方式实现,并且可以更深入地搜索有效类型,它可以将对象绑定到对象的目的(即实现接口而不仅仅是对象的实际类型。但这不是它的实现方式,而且这样做成本会高得多(无论是在原始设计和实现方面,还是在使用dynamic
的代码的运行时成本方面)。
相关阅读(可以说是重复的):
Is this a bug in dynamic?
Is this a hole in dynamic binding in C# 4?