2009-09-05 5 views
8
private void StringAction(string aString) // method to be called 
{ 
    return; 
} 

private void TestDelegateStatement1() // doesn't work 
{ 
    var stringAction = new System.Action(StringAction("a string")); 
    // Error: "Method expected" 
} 

private void TestDelegateStatement2() // doesn't work 
{ 
    var stringAction = new System.Action(param => StringAction("a string")); 
    // Error: "System.Argument doesn't take 1 arguments" 

    stringAction(); 
} 

private void TestDelegateStatement3() // this is ok 
{ 
    var stringAction = new System.Action(StringActionCaller); 

    stringAction(); 
} 

private void StringActionCaller() 
{ 
    StringAction("a string"); 
} 

Ich verstehe nicht, warum TestDelegateStatement3 funktioniert, aber TestDelegateStatement1 versagt. In beiden Fällen wird Action mit einer Methode geliefert, die Null Parameter akzeptiert. Sie können Aufruf eine Methode, die einen einzigen Parameter (aString), aber das sollte irrelevant sein. Sie nehmen keinen Parameter. Ist das mit Lamda-Ausdrücken nicht möglich, oder mache ich etwas falsch?Verwirrung über `Action` Delegaten und Lambda-Ausdrücke

Antwort

18

Wie Sie gesagt haben, nimmt Action keine Parameter. Wenn Sie dies tun:

var stringAction = new System.Action(StringAction("a string")); 

Sie tatsächlich die Methode hier ausführen, so dass kein Methodenparameter ist.

wenn Sie dies tun:

var stringAction = new System.Action(param => StringAction("a string")); 

Sie es sagen, dass Ihre Methode einen Parameter param, die Aktion tut genannt nimmt nicht.

Also der richtige Weg sein würde dies zu tun:

var stringAction = new System.Action(() => StringAction("a string")); 

oder kompaktere:

Action stringAction =() => StringAction("a string"); 

die leeren Klammern werden verwendet, um das Lambda, um anzuzeigen, keine Parameter übernehmen.

+0

@Botz:
new Action<string>(myStringParam => StringAction(myStringParam));

Also, in Ihrem Fall vollständiger Code würde wie folgt aussehen min oder Korrektur zu Ihrer "kompakteren" Anweisung: 'System.Action stringAction =() => StringAction (" eine Zeichenkette ");' (Der Compiler hat nicht genug Informationen, um zu wissen, dass 'var' eine' System.Action ist '). – devuxer

+0

Oh, danke. Das wurde behoben. – Botz3000

2

In C# 2.0 ist der Action Delegat ein void Delegat, der Parameter nicht akzeptiert. In späteren Versionen gibt es den allgemeinen Delegaten Action<T>, wobei T den Parametertyp angibt.

Dies sollte funktionieren:

var stringAction = new Action<string>(param => StringAction(param)); 

oder noch besser:

var stringAction = new Action<string>(StringAction); // using method group conversion 

dann, Sie

stringAction("Hello world"); 
4

nennen kann ich auf diese kein Experte bin, aber haben Sie versuchte das?

public void TestDelegateStatement4 
{ 
    var stringAction =() => StringAction("a string"); 
} 
4

Action Der Delegat ist als Delegat für die Methode definiert, die keine Parameter hat und void zurückgibt. In Beispiel 1 machen Sie 2 Fehler:
1. Sie versuchen, Methode zu geben, die Parameter
nimmt 2. Sie rufen die Methode auf und geben es nicht als Parameter (es sollte neu sein Aktion (MethodName)), obwohl es wegen 1 nicht funktionieren würde.

In Probe 2, Sie wieder den gleichen Fehler machen, Ihre Lambda einen Parameter nimmt, sollten Sie es wie folgt schreiben:
new Action(() => StringAction("a string"));

Wenn Sie einen Delegaten erstellen möchten, die einen Parameter nehmen , sollten Sie es wie folgt tun:


private void StringAction(string aString) // method to be called 
{ 
    return; 
} 

private void TestDelegateStatement1() // now it works 
{ 
    var stringAction = new Action<string>(StringAction); 
    //You can call it now: 
    stringAction("my string"); 
} 

private void TestDelegateStatement2() // now it works 
{ 
    var stringAction =() => StringAction("a string"); 
    //Or the same, with a param: 
    var stringActionParam = (param) => StringAction(param); 

    //You can now call both: 
    stringAction(); 
    stringActionParam("my string"); 
} 

private void TestDelegateStatement3() // this is ok 
{ 
    var stringAction = new System.Action(StringActionCaller); 

    stringAction(); 
} 

private void StringActionCaller() 
{ 
    StringAction("a string"); 
}