Func-Delegat ohne Rückgabetyp


561

Alle Func-Delegaten geben einen Wert zurück. Welche .NET-Delegaten können mit Methoden verwendet werden, die void zurückgeben?

Antworten:


759

Alle Func-Delegierten geben etwas zurück. Alle Aktionsdelegierten kehren ungültig zurück.

Func<TResult> nimmt keine Argumente und gibt TResult zurück:

public delegate TResult Func<TResult>()

Action<T> nimmt ein Argument und gibt keinen Wert zurück:

public delegate void Action<T>(T obj)

Action ist der einfachste, "nackte" Delegierte:

public delegate void Action()

Es gibt auch Func<TArg1, TResult>und Action<TArg1, TArg2>(und andere bis zu 16 Argumente). Alle diese (außer Action<T>) sind neu in .NET 3.5 (definiert in System.Core).


11
Zu Ihrer Information, die nächste Version der Basisklassenbibliothek wird Func- und Action-Typen enthalten, die mehr als vier formale Parameter unterstützen. Ich erinnere mich nicht genau, wie groß sie werden.
Eric Lippert

88
In .NET 4.0 werden jetzt bis zu 8 Parameter verwendet. Wenn sie so weitermachen, wird es in der nächsten Version bis elf gehen !! 11 !!!
Michiel van Oosterhout

9
Eigentlich sieht es so aus, als würden sie in 4.0 auf 16 steigen.
Tustin2121

7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... Dies zeigt deutlich, dass der Compiler in der Lage sein muss, mehr Argumente für eine Funktion zu verarbeiten, als dies derzeit zu einem späteren Zeitpunkt der Fall ist !
Chris Morgan

6
Tatsächlich ist Tustin2121 richtig, sie haben Func<,,, ... ,>in .NET 4.0 bis zu 16 Parameter (plus einen Rückgabetyp im Fall von ) erreicht, aber die letzten acht Typen jeder "Serie" sind in definiert System.Core.dll, nicht in mscorlib.dll, also wäre dies der Grund warum michielvoo sie nicht gesehen hat. In den .NET-Versionen 4.5 und 4.5.1 wurden jedoch keine Funktionen oder Aktionen mehr hinzugefügt. Wird diese Sequenz zu A170836 oder A170875 ? Bleib dran.
Jeppe Stig Nielsen

83

... keine Argumente akzeptiert und einen ungültigen Rückgabetyp hat?

Ich glaube, das Actionist eine Lösung.


47

Alle Func-Delegierten verwenden mindestens einen Parameter

Das ist nicht wahr. Sie alle verwenden mindestens ein Typargument, aber dieses Argument bestimmt den Rückgabetyp.

So Func<T>übernimmt keine Parameter und gibt einen Wert. Verwenden Sie Actionoder, Action<T>wenn Sie keinen Wert zurückgeben möchten.


27

Versuchen Sie System.Func<T>undSystem.Action


1
Ich glaube nicht, dass das 0-Argument und so weiter in .Net 2.0 existiert.
Brian

1
Es ist seltsam: Func existiert in .Net 2.0 überhaupt nicht, Predicate und Action jedoch.
Joel Coehoorn

2
Verwenden Sie für .NET 2.0 den MethodInvoker-Delegaten.
Trevor Elliott

.NET 2 hatte (oder hat) auch einen Delegatentyp, Converter<TInput, TOutput>der dem späteren ähnelte Func<T, TResult>. Es wurde in der List<>.ConvertAllMethode verwendet, die jedes Element in einem List<>auf ein anderes Objekt projizierte und alle "Funktionswerte" in ein neues platzierte List<>. (Später benutzte man oft Linq Selectdafür.)
Jeppe Stig Nielsen

0

Gelegentlich möchten Sie einen Delegaten für die Ereignisbehandlung schreiben. In diesem Fall können Sie den Vorteil nutzen, der zusätzlich zu dem zweiten Parameter, von System.EvenHandler<T>dem abgeleitet werden soll, implizit ein Argument vom Typ akzeptiert . EventHandlers kehren zurückobjectEventArgsvoid

Ich persönlich fand dies beim Testen nützlich, um einen einmaligen Rückruf in einem Funktionskörper zu erstellen.


0

... keine Argumente akzeptiert und einen ungültigen Rückgabetyp hat?

Wenn Sie für schreiben System.Windows.Forms, können Sie auch Folgendes verwenden:

public delegate void MethodInvoker()

0

Eine sehr einfache Möglichkeit, Subroutinen für Rückgabewerte und Nichtrückgabewerte aufzurufen. verwendet Func bzw. Action . (Siehe auch https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Versuchen Sie dies in diesem Beispiel

using System;

public class Program
{
    private Func<string,string> FunctionPTR = null;  
    private Func<string,string, string> FunctionPTR1 = null;  
    private Action<object> ProcedurePTR = null; 



    private string Display(string message)  
    {  
        Console.WriteLine(message);  
        return null;  
    }  

    private string Display(string message1,string message2)  
    {  
        Console.WriteLine(message1);  
        Console.WriteLine(message2);  
        return null;  
    }  

    public void ObjectProcess(object param)
    {
        if (param == null)
        {
            throw new ArgumentNullException("Parameter is null or missing");
        }
        else 
        {
            Console.WriteLine("Object is valid");
        }
    }


    public void Main(string[] args)  
    {  
        FunctionPTR = Display;  
        FunctionPTR1= Display;  
        ProcedurePTR = ObjectProcess;
        FunctionPTR("Welcome to function pointer sample.");  
        FunctionPTR1("Welcome","This is function pointer sample");   
        ProcedurePTR(new object());
    }  
}

1
Vielen Dank für dieses Code-Snippet, das möglicherweise nur begrenzte, sofortige Hilfe bietet. Eine richtige Erklärung würde ihren langfristigen Wert erheblich verbessern, indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und es für zukünftige Leser mit anderen, ähnlichen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, einschließlich der von Ihnen getroffenen Annahmen.
iBug
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.