2010-08-02 8 views
15

Dies ist mein Test-Code für den Parameter:Argumenttyp ‚VOID‘ ist nicht übertragbar Typ ‚System.Action‘

class PassingInActionStatement 
{ 
    static void Main(string[] args) 
    { 
     var dsufac = new DoSomethingUsefulForAChange(); 

     dsufac.Do(WriteToConsole); 
     dsufac.Do2(s => WriteToConsoleWithSomethingExtra("Test")); 
     dsufac.Do(WriteToConsoleWithSomethingExtra("Test")); // Does not compile 
    } 

    internal static void WriteToConsole() 
    { 
     Console.WriteLine("Done"); 
    } 

    internal static void WriteToConsoleWithSomethingExtra(String input) 
    { 
     Console.WriteLine(input); 
    } 
} 

internal class DoSomethingUsefulForAChange 
{ 
    internal void Do(Action action) 
    { 
     action(); 
    } 

    internal void Do2(Action<String> action) 
    { 
     action(""); 
    } 
} 

Die ersten 2 Anrufe arbeiten, aber ich frage mich, warum die dritte man nicht. Ich mag den Code in Do2 nicht, da es merkwürdig erscheint, dass ich den Typ action("") dort eingegeben habe, um es zum Laufen zu bringen.

Könnte jemand bitte die 2 Dinge erklären, die ich nicht verstehe bitte?

  1. Warum ich nicht die dritte Zeile wie die mit Aufruf Do
  2. Warum ich Aktion schreiben muß („“), um es tatsächlich in Do2
+0

ich immer Antworten markiert, die mir geholfen. Wenn es keine Lösung gibt, die etwas Nützliches bietet, markiere ich es nicht, bis ich die Antwort bekomme, die mir hilft. –

Antwort

32
dsufac.Do(WriteToConsoleWithSomethingExtra("Test")); 

an der Arbeit schreiben kann ruft die Funktion zuerst auf (WriteToConsoleWithSomethingExtra("Test")) und versucht dann, das Ergebnis in Do zu übergeben. Da es kein Ergebnis gibt (void), ist das nicht möglich.

Was Sie wirklich wollen, ist dies:

dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test")); 

Der innere Teil erklärt eine Funktion, die nichts (das () => Bit) hat, die WriteToConsoleWithSomethingExtra("Test") ruft bei seiner Ausführung. Dann Ihre dsufac.Do Aufruf wird eine Aktion erhalten, wie es erwartet.

Was Do2 - Sie haben es erklärt Action<String> als Einnahme, was bedeutet, dass action ist eine Funktion, dass ein Argument. Sie müssen eine Zeichenfolge übergeben. Dieser String kann leer sein, wie in Ihrem action("") Beispiel, oder es könnte in nach außen geführt werden, wie es in etwa so:

dsufac.Do3(WriteToConsole, "Test"); 

... 

internal void Do3(Action<String> action, String str) 
{ 
    action(str); 
} 
+0

Waw! Das funktioniert. Ich habe immer noch viele Probleme mit diesen Action- und Func-Sachen. Gibt es anständige Tutorials neben MSDN oder Bücher, die Sie vorschlagen können? Ich werde deine Antwort als solche markieren, wenn sie es mir erlaubt (anscheinend noch ein paar Minuten warten müssen). –

+0

Danke für das Extra-Update. –

1
  1. Do erwartet eine Action (dh Methode, die keine Parameter übernehmen und gibt keinen Wert zurück). Daher ist WriteToConsoleWithSomethingExtra keine gültige Anpassung - nimmt einen String-Parameter.
  2. Do2 akzeptiert eine Action<T> (d. H. Eine Methode, die einen T-Parameter akzeptiert und keinen Wert zurückgibt). Daher müssen Sie, wenn Sie den Delegaten/die Aktion aufrufen, einen Parameter vom Typ T angeben, hier String.
3

In Ihrem Code

dsufac.Do(WriteToConsoleWithSomethingExtra("Test")); 

wie folgt

var variable = WriteToConsoleWithSomethingExtra("Test"); 
dsufac.Do(variable); 

Als Rückgabetyp WriteToConsoleWithSomethingExtra interpretiert wird ("Test") ist ungültig, so dass man eigentlich nicht passieren kann es zu dsufa.Do(). Deshalb wird es nicht kompiliert. Aber für den ersten

dsufac.Do(WriteToConsole); 

Sie rufen nicht die Funktion, sondern Sie es als eine Methode Gruppe vorbei, die später in dem Do() -Methode des dsufac Objekts aufgerufen erhalten wird.Aber wenn man die dritte Zeile wie die erste schreiben möchten, können Sie verwenden

dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test")); 
1

Ich wurde in einer Silverlight-Anwendung für eine Weile so etwas wie dies zu tun. Jetzt, wenn es läuft, bricht ein Teil davon.
Dies geschieht in einem Silverlight-Kind-Fenster:

(my object context).SaveChanges(() => ChangesSaved()); 

private void ChagngesSaved() 
{ 
    DialogResult = true: // is supposed to close the child window. line gets hit, does not close 
} 
Verwandte Themen