私有内部 class 上的动态失败

Dynamic fails on private inner class

当我 运行 以下代码时,我得到 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> 是私有内部 class 有关,因为它在我制作它时起作用 public.

这是您的问题的一个简单示例:

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>)是私有类型 class,因此在调用站点无法解析为该实际类型.回想一下,dynamic 只是一个 object 变量,但编译已推迟到 运行 时间。它的目的不是让你在 运行 时间做你本来无法做的事情,并且 "wouldn't otherwise be able to do" 是根据调用站点的可访问类型来判断的(在这种情况下, 是 object).

就 运行time 活页夹而言,类型只是 object(因此错误消息告诉您 object 不包含您想要的成员) .

当然,理论上 dynamic 可以有不同的实现方式,并且可以对有效类型进行更深入的搜索,它可以将对象视为将成员绑定到对象(即实现的接口而不仅仅是对象的实际类型)。但这并不是它的实现方式,而且这样做的成本要高得多(无论是在原始设计和实现方面,当然还是在 运行 的代码时间成本方面,使用 dynamic).

相关阅读(可以重复):

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