2009-09-05 10 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"); 
} 

Non capisco il motivo per cui TestDelegateStatement3 opere ma TestDelegateStatement1 fallisce. In entrambi i casi, Action viene fornito con un metodo che accetta zero parametri. Possono chiamare un metodo che accetta un singolo parametro (aString), ma che dovrebbe essere irrilevante. Non prendono un parametro. Non è proprio possibile farlo con le espressioni lamda o sto facendo qualcosa di sbagliato?Confusione su `Action` delegato ed Espressioni lambda

risposta

18

Come hai detto, l'azione non ha alcun parametro. Se si esegue questa operazione:

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

In realtà si esegue il metodo qui, in modo che non è un parametro del metodo.

se si fa questo:

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

gli dite che il vostro metodo prende un parametro chiamato param, che Azione non lo fa.

Quindi il modo corretto per fare questo sarebbe:

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

o più compatto:

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

le staffe vuote sono usati per indicare il lambda non prende alcun parametro.

+0

@Botz: min o correzione alla tua istruzione "più compatta": 'System.Action stringAction =() => StringAction (" a string ");' (il compilatore non ha abbastanza informazioni per sapere che 'var' è un' System.Action '). – devuxer

+0

Oh, grazie. Risolto il problema. – Botz3000

2

In C# 2.0, il delegato Action è un delegato void che non accetta i parametri. Nelle versioni successive, c'è il delegato generico Action<T>, dove T specifica il tipo di parametro.

Questo dovrebbe funzionare:

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

o meglio ancora:

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

allora, è possibile chiamare

stringAction("Hello world"); 
4

Io non sono un esperto su questo, ma hai provato questo?

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

Action delegato è definito come delegato al metodo, che non ha parametri e restituisce void. Nell'esempio 1, si stanno commettendo 2 errori:
1. Si sta provando a fornire il metodo, che utilizza il parametro
2. Si sta richiamando il metodo e non lo si fornisce come parametro (dovrebbe essere una nuova azione (methodName)), anche se non funzionerebbe a causa di 1.

Nel campione 2, si stanno facendo lo stesso errore, il tuo lambda sta prendendo un parametro, si dovrebbe scrivere in questo modo:
new Action(() => StringAction("a string"));

Se si desidera creare un delegato, che avrà un parametro , si dovrebbe fare in questo modo:
new Action<string>(myStringParam => StringAction(myStringParam));

Quindi, nel tuo caso, codice completo sarebbe simile a questa:


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