4 Stimmen

Können bei der Verwendung dynamischer Variablen generische Parameter angegeben werden?

Betrachten Sie den folgenden Code:

class Program {
    void Foo<T>() { }

    static void Main(string[] args) {
        dynamic p = new Program();
        p.Foo();
    }
}

Überraschenderweise ist der Aufruf von p.Foo() nicht gültig, da der dynamische Binder nicht weiß, welcher Typ für T zu verwenden ist:

" Die Typargumente für die Methode 'ConsoleApplication1.Program.Foo()' können nicht aus der Verwendung abgeleitet werden. Versuchen Sie, die Typargumente explizit anzugeben. "

Meine Frage ist nun: Gibt es eine Möglichkeit, den generischen Typ zu spezifizieren, oder ist eine solche Methode einfach nicht mit "dynamic" aufrufbar?

14voto

Jon Skeet Punkte 1325502

Wie Jared sagt, können Sie es im Code genauso angeben, wie Sie es bei einem statischen Aufruf tun würden:

using System;

class Program {
    void Foo<T>() {
        Console.WriteLine(typeof(T));
    }

    static void Main(string[] args) {
        dynamic p = new Program();
        p.Foo<string>();
    }
}

Der obige Code druckt System.String .

Wenn Sie jetzt nur wüssten TAusführung Zeit, ist es etwas schwieriger. Wenn Sie jedoch eine Instanz davon haben, können Sie dynamische Typisierung und Typinferenz zusammen verwenden:

using System;

class Program {
    void Foo<T>() {
        Console.WriteLine(typeof(T));
    }

    static void Main(string[] args) {
        dynamic p = new Program();
        dynamic v = GetRandomInstance();

        // Now to call p.Foo<T> where T is the type of v's value...
        Dummy(v, p);
    }

    static void Dummy<T>(T t, Program p) {
        p.Foo<T>();
    }

    static object GetRandomInstance() {
        return DateTime.Now.Hour > 10 ? "hello" : (object) 10;
    }
}

EDIT: Pavel hat in den Kommentaren eine tolle Idee geäußert. Sie müssen nicht mit einer Instanz von T nur ein Array. Das bedeutet, dass Sie sogar Typargumente verwenden können, bei denen das normalerweise nicht möglich ist bekommen. eine Instanz von T (z.B. durch einen privaten Konstruktor):

using System;

class PrivateConstructor {
    private PrivateConstructor() {}
}

class Program {
    static void Foo<T>() {
        Console.WriteLine(typeof(T));
    }

    static void CallFooProxy<T>(T[] array) {
        Foo<T>();
    }

    static void CallFoo(Type t) {
        dynamic array = Array.CreateInstance(t, 0);
        CallFooProxy(array);
    }

    static void Main(string[] args) {
        CallFoo(typeof(PrivateConstructor));
    }
}

Bevor jemand fragt - nein, damit kann man nicht anrufen Foo<Enumerable> dynamisch - Sie können eine statische Klasse immer noch nicht als Typargument verwenden, auch wenn Sie versuchen, den Versuch bis zur Ausführungszeit zu verzögern :)

Wenn all das aus irgendeinem Grund fehlschlägt, geht es wieder zurück zur normalen Reflexion... die Methodeninformationen abrufen, die MakeGenericMethod und rufen sie auf.

2voto

JaredPar Punkte 699699

Warum geben Sie den Typ nicht genau so an, wie Sie es bei einem nicht-dynamischen Typ tun würden

p.Foo<int>();

1voto

Reed Copsey Punkte 536986

In diesem Fall spielt es keine Rolle, welcher Typ "p" ist, ob Sie ihn als dynamisch oder als Programm erhalten Sie diese Fehlermeldung.

Der Fehler besagt, dass der Typ von T nicht abgeleitet werden kann, weil es keine Parameter des Typs T an die Methode übergeben wird, und die Methode nicht Teil einer generischen Klasse ist. In diesem Fall gibt es für den Compiler keine Möglichkeit, auf den Typ T zu schließen.

Sie sollten jedoch in der Lage sein, Folgendes zu tun:

class Program {
    void Foo<T>() { }

    static void Main(string[] args) {
        dynamic p = new Program();
        p.Foo<int>();
    }
}

Sie müssen nur den Typ von T explizit definieren, wenn Sie Foo aufrufen.

0voto

dahlbyk Punkte 71222

Warum konnten Sie nicht angeben, dass T es dynamic ?

p.Foo<dynamic>();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X