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

No entiendo por qué funciona, pero TestDelegateStatement3TestDelegateStatement1 falla. En ambos casos, Action se suministra con un método que toma cero parámetros. Pueden llamar al un método que toma un solo parámetro (aString), pero eso debería ser irrelevante. No toman un parámetro. ¿Esto no es posible con expresiones lamda o estoy haciendo algo mal?`action delegado y lambda expresiones

Respuesta

18

Como dijiste, Action no toma ningún parámetro. Si hace esto:

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

En realidad se ejecuta el método aquí, así que no es un parámetro del método.

si hace esto:

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

usted le dice que su método toma un parámetro llamado param, acción que no lo hace.

Así que la forma correcta de hacer esto sería:

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

o más compacta:

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

los corchetes vacíos se utilizan para indicar la lambda no toma ningún parámetro.

+0

@Botz: min o corrección a su afirmación "más compacta": 'System.Action stringAction =() => StringAction (" a string ");' (el compilador no tiene suficiente información para saber que 'var' es' System.Action '). – devuxer

+0

Oh, gracias. Solucionado eso. – Botz3000

2

En C# 2.0, el delegado Action es un delegado void que no acepta parámetros. En versiones posteriores, está el delegado genérico Action<T>, donde T especifica el tipo de parámetro.

Esto debería funcionar:

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

o incluso mejor:

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

continuación, puede llamar

stringAction("Hello world"); 
4

No soy un experto en esto, pero ¿ha intenté esto?

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

Action delegado se define como delegar en el método, que no tiene parámetros y devuelve vacío. En la muestra 1, está cometiendo 2 errores:
1. Está intentando dar el método, que toma el parámetro
2. Está invocando el método, y no dándole como parámetro (debe ser una nueva Acción (methodName)), aunque no funcionaría debido a 1.

En la muestra 2, que están haciendo el mismo error otra vez, su lambda está tomando un parámetro, debe escribir así:
new Action(() => StringAction("a string"));

Si desea crear un delegado, que tendrá un parámetro , debe hacerlo de esta manera:
new Action<string>(myStringParam => StringAction(myStringParam));

Así, en su caso, código completo se vería así:


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