2016-04-08 5 views
0

Ich spiele mit Delegierten herum, aber ich verstehe offensichtlich nicht etwas Grundlegendes."Objekt stimmt nicht mit Zieltyp überein" auf Basis Delegiertenbeispiel

class Test 
{ 
    delegate bool Foo(); 

    public void Run() 
    { 
     Delegate foo = new Foo((delegate() { return true; })); 
     bool result = (bool)foo.Method.Invoke(foo, null); 
    } 
} 

Test test = new Test(); 
test.Run(); 

Im obigen Beispiel begegne ich eine Ausnahme:

Ich habe folgendes bekam. „Object nicht Zielart entsprechen“

Folgende Werke in Ordnung, aber:

class Test 
{ 
    delegate bool Foo(); 

    public void Run() 
    { 
     Foo foo = new Foo((delegate() { return true; })); 
     bool result = foo.Invoke(); 
    } 
} 

Test test = new Test(); 
test.Run(); 

Was mit meiner ersten Implementierung falsch ist? Sollte ich nicht fo's Methode als foo ohne Parameter aufrufen? Dies würde dem letzteren Code entsprechen.

Antwort

3

Sie umgehen den gesamten Grund, warum Sie den Delegierten überhaupt verwenden würden. Als Faustregel gilt: nicht berührenMethod.

Das erste Argument in MethodInfo.Invoke ist die this Instanz. Dies kann null oder etwas anderes sein (z. B. eine Schließung oder die tatsächliche Objektinstanz, wenn der Delegat eine Instanzmethode darstellt), aber es wird niemals die Delegateninstanz sein - das macht keinen Sinn.

In Ihrem Fall ist es in der Tat eine Schließung Instanz. Aber Sie haben keinen Hinweis auf die Schließung außerhalb des Delegaten - es wird hinter der Szene vom Compiler erstellt. Der einzige geeignete Weg für den Aufruf (MethodInfo) wäre foo.Method.Invoke(foo.Target, null);. Natürlich ist das völlig redundant - verwenden Sie einfach foo(); wie jeder vernünftige Mensch, und Sie werden gut sein :)

Auf die gleiche Weise aufhören, die alte Delegate Syntax zu verwenden. Das hat wenig Sinn. Eine einfache

Func<bool> foo =() => true; 
Console.WriteLine(foo()); 

wird gut funktionieren. Sie können Ihren eigenen Delegaten für Func<bool> ersetzen, wenn Sie wirklich brauchen, aber die Verwendung von benutzerdefinierten Delegaten ist heutzutage nicht sehr nützlich.

+0

Danke. Dieser Beispielcode wird aus einer viel größeren Codebasis extrahiert, weshalb der Code selbst seltsam erscheint. Versuchen zu verstehen, warum eine Ausnahme ausgelöst wird, müssen aber zuerst die Mechanik der Delegierten lernen. –

+0

@SeanAnderson Delegierte sind sehr einfach - sie sind nur das Ziel und die Methode, die aufgerufen werden soll. Sie sind wie eine Schnittstelle mit einer einzigen Methode :) Es sei denn, Sie tun Reflexion Mumbo-Jumbo, Sie interessieren sich auch nicht - nur "Invoke" (oder besser, '(...)'), und Sie Mir geht es gut. Wenn jemand 'Delegate.Method.Invoke' anstelle von' Delegate.Invoke' verwendet, finde sie und frage nach dem Grund. Bringen Sie einen Baseballschläger für alle Fälle mit. – Luaan

+0

Der Code ist in der Tat Reflexion Mumbo-Jumbo. Die Reflektion scheint aufgrund eines veralteten Verweises auf eine DLL, über die wir nachzudenken versuchen, fehlzuschlagen. Aber nicht 100% sicher, weshalb ich versuche, das Problem zuerst ein wenig zu beseitigen. Ich schätze die ausführliche Antwort jedoch. –