2017-09-26 99 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?