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

Nie rozumiem dlaczego TestDelegateStatement3 prace ale TestDelegateStatement1 zawiedzie. W obu przypadkach Action jest dostarczany z metodą, która przyjmuje parametry zerowe. Mogą one wywoływać pojedynczy parametr(), ale to powinno być nieistotne. Nie biorą parametru. Czy nie jest to po prostu możliwe w przypadku wyrażeń lamda, czy też robię coś nie tak?Zamieszanie na `action delegata i lambda wyrażenia

Odpowiedz

18

Tak jak powiedziałeś, Action nie przyjmuje żadnych parametrów. Jeśli to zrobić:

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

rzeczywiście wykonać metodę tutaj, więc nie jest to parametr metody.

jeśli to zrobić:

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

poinformować go, że metoda przyjmuje parametr o nazwie param, których działanie nie.

więc poprawny sposób to zrobić byłoby:

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

lub bardziej zwarty:

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

puste nawiasy są używane do wskazania lambda nie ma żadnych parametrów.

+0

@Botz: min lub poprawka do "bardziej zwartej" instrukcji: 'System.Action stringAction =() => StringAction (" string ");' (kompilator nie ma wystarczających informacji, aby wiedzieć, że 'var' jest' System.Action '). – devuxer

+0

Och, dzięki. Naprawiono to. – Botz3000

2

W języku C# 2.0 delegat Action jest delegatem void, który nie przyjmuje parametrów. W nowszych wersjach dostępny jest delegat Action<T>, gdzie T określa typ parametru.

To powinno działać:

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

lub nawet lepiej:

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

następnie można nazwać

stringAction("Hello world"); 
4

nie jestem ekspertem w tej sprawie, ale czy próbowałeś tego?

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

Action Delegat jest zdefiniowany jako delegat do metody, która nie ma parametrów i zwraca nieważne. W przykładzie 1 popełniasz 2 błędy:
1. Próbujesz podać metodę, która przyjmuje parametr
2. Wywołujesz tę metodę i nie nadajesz jej jako parametru (powinna to być nowa Akcja (nazwa metody)), chociaż nie zadziałałoby z powodu 1.

W próbce 2, pojawi się znowu tego samego błędu, twój lambda bierze parametr, należy napisać to tak:
new Action(() => StringAction("a string"));

Jeśli chcesz utworzyć delegata, który odbędzie się parametr , należy zrobić to tak:
new Action<string>(myStringParam => StringAction(myStringParam));

Więc w twoim przypadku, kompletny kod będzie wyglądać następująco:


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"); 
} 
Powiązane problemy