2017-09-26 136 views
2

当我运行下面的代码时,我得到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); 
    } 
} 

如果我切换thingvar它工作正常。所以很清楚,thingSetIt。当我使用动态时,这怎么会失败?当它是dynamic时,不应该作为var工作的任何东西也能工作吗?

我认为它与Thing<TInput>是私人内部类有关,因为它在我公开时起作用。

回答

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变量,但编译已经推迟到运行时。它不打算让你在运行时做一些你不能做的事情,并且“根本无法做到”是根据调用站点的可访问类型(在此情况,是object)。

就运行时联编程序而言,类型仅仅是object(因此错误消息告诉您object不包含您想要的成员)。

当然,理论上dynamic可能已经以不同的方式实现了,并且可以更深入地搜索它可以处理对象的有效类型,以便将成员绑定到对象(即实现的接口而不仅仅是对象的实际类型)。但这并不是如何实现的,而且这样做会更加昂贵(无论是在原始设计和实现方面,还是在使用dynamic的代码的运行时代码方面)。

相关读数(可以说是一式两份):

Is this a bug in dynamic?
Is this a hole in dynamic binding in C# 4?