Delegato di Func senza tipo restituito


561

Tutti i delegati di Func restituiscono un valore. Quali sono i delegati .NET che possono essere utilizzati con metodi che restituiscono nulla?

Risposte:


760

Tutti i delegati di Func restituiscono qualcosa; tutti i delegati dell'Azione ritornano nulli.

Func<TResult> non accetta argomenti e restituisce TResult:

public delegate TResult Func<TResult>()

Action<T> accetta un argomento e non restituisce un valore:

public delegate void Action<T>(T obj)

Action è il delegato più semplice, "nudo":

public delegate void Action()

C'è anche Func<TArg1, TResult>e Action<TArg1, TArg2>(e altri fino a 16 argomenti). Tutti questi (ad eccezione di Action<T>) sono nuovi a .NET 3.5 (definito in System.Core).


11
Cordiali saluti, la prossima versione della libreria di classi base includerà i tipi Func e Action che supportano più di quattro parametri formali. Non ricordo esattamente quanto diventano grandi.
Eric Lippert,

88
In .NET 4.0 ora vanno fino a 8 parametri. Se continuano così, nella prossima versione saliranno fino alle undici !! 11 !!!
Michiel van Oosterhout,

9
In realtà, sembra che salgano a 16 in 4.0.
Tustin2121,

7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... questo indica chiaramente che il compilatore dovrà essere in grado di far fronte a più argomenti di una funzione di quanto non faccia attualmente in futuro !
Chris Morgan,

6
In realtà, Tustin2121 ha ragione, sono saliti a 16 parametri (più un tipo di ritorno nel caso di Func<,,, ... ,>) in .NET 4.0, ma gli ultimi otto tipi di ogni "serie" sono definiti in System.Core.dll, non in mscorlib.dll, quindi questo sarebbe il motivo perché michielvoo non li ha visti. Tuttavia, non sono stati aggiunti altri Func o azioni nelle versioni .NET 4.5 e 4.5.1. Questa sequenza diventerà A170836 o A170875 ? Rimanete sintonizzati.
Jeppe Stig Nielsen,

83

... non accetta argomenti e ha un tipo di ritorno vuoto?

Credo Actionsia una soluzione a questo.


47

Tutti i delegati di Func accettano almeno un parametro

Non è vero. Prendono tutti almeno un argomento di tipo, ma quell'argomento determina il tipo di ritorno.

Quindi Func<T>non accetta parametri e restituisce un valore. Utilizzare Actiono Action<T>quando non si desidera restituire un valore.


27

Prova System.Func<T>eSystem.Action


1
Non credo che 0 arg e quant'altro esista in .Net 2.0, però.
Brian,

1
È strano: Func non esiste affatto in .Net 2.0, anche se Predicate e Action lo fanno.
Joel Coehoorn,

2
Per .NET 2.0 utilizzare il delegato MethodInvoker.
Trevor Elliott,

Anche .NET 2 aveva (o ha) un tipo delegato Converter<TInput, TOutput>simile a quello successivo Func<T, TResult>. È stato utilizzato nel List<>.ConvertAllmetodo che ha proiettato ogni elemento in a List<>su un altro oggetto e ha inserito tutti i "valori di funzione" in un nuovo List<>. (Più tardi, si userebbe spesso Linq Selectper quello.)
Jeppe Stig Nielsen,

0

Occasionalmente vorrai scrivere un delegato per la gestione degli eventi, nel qual caso puoi trarne vantaggio System.EvenHandler<T>accettando implicitamente un argomento di tipo objectoltre al secondo parametro da cui dovrebbe derivare EventArgs. EventHandlers torneràvoid

Personalmente l'ho trovato utile durante i test per la creazione di un callback unico in un corpo di funzione.


0

... non accetta argomenti e ha un tipo di ritorno vuoto?

Se stai scrivendo per System.Windows.Forms, puoi anche usare:

public delegate void MethodInvoker()

0

Un modo molto semplice per invocare subroutine di valore di ritorno e non di ritorno. sta usando rispettivamente Func e Action . (vedi anche https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Prova questo esempio

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
Grazie per questo frammento di codice, che potrebbe fornire un aiuto immediato e limitato. Una spiegazione adeguata migliorerebbe notevolmente il suo valore a lungo termine mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con altre domande simili. Si prega di modificare la risposta di aggiungere qualche spiegazione, tra le ipotesi che hai fatto.
iBug
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.