私有内部类的动态失败

时间:2017-09-26 02:58:35

标签: c# dynamic inner-classes

当我运行以下代码时,我得到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,则可以正常使用。很明显,thingSetIt。当我使用动态时,怎么会失败呢?任何适用于var的内容都不应该在dynamic时起作用吗?

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

1 个答案:

答案 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?