2017-09-26 1 views
2

Wenn ich den folgenden Code ausführen, bekomme ich RuntimeBinderException: 'object' does not contain a definition for 'SetIt'.Dynamische Fehler auf private innere Klasse

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); 
    } 
} 

Wenn ich thing zu einem var wechseln funktioniert es gut. Also klar, thing hat SetIt. Wie kommt das, wenn ich dynamisch benutze? Sollte keine Sache, die als var funktioniert auch funktionieren, wenn es dynamic ist?

Ich denke, es hat etwas mit Thing<TInput> eine private innere Klasse zu tun, weil es funktioniert, wenn ich es öffentlich mache. Hier

Antwort

1

ist ein einfacheres Beispiel für Ihr Problem:

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(); 
    } 
} 

Die Generika und Schnittstellen sind nur eine Ablenkung.

Das Problem ist, dass der Typ B (oder in Ihrem Fall Thing<IInput>) eine private Klasse ist, und so bei der Aufruf-Site, kann nicht zu diesem tatsächlichen Typ aufgelöst werden. Erinnern Sie sich, dass dynamic einfach eine object Variable ist, aber die Kompilierung wurde bis zur Laufzeit verschoben. Es ist nicht vorgesehen, dass Sie Dinge zur Laufzeit ausführen, die Sie sonst nicht tun könnten, und "würde nicht anders können" wird basierend auf dem zugänglichen Typ auf der Aufrufseite beurteilt (was in diesem Fall nicht möglich ist) Fall, ist object).

Soweit der Runtime-Binder betroffen ist, ist der Typ einfach object (daher die Fehlermeldung, dass object nicht das gewünschte Mitglied enthält).

Natürlich ist es theoretisch möglich, dass dynamic anders implementiert worden sein könnte, und könnte eine tiefergehende Suche nach gültigen Typen, die das Objekt behandeln könnten, um Mitglieder an das Objekt zu binden (dh implementierte Schnittstellen) anstatt nur den tatsächlichen Typ des Objekts). Aber so wurde es nicht implementiert, und es wäre viel kostspieliger gewesen, dies zu tun (sowohl in Bezug auf das ursprüngliche Design und die Implementierung als auch natürlich in Bezug auf Laufzeitkosten von Code, der dynamic verwendet).

Verwandte Lesung (wohl Duplikate):

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

Verwandte Themen