Delegado Func sin tipo de retorno

561

Todos los delegados de Func devuelven un valor. ¿Cuáles son los delegados .NET que se pueden usar con métodos que devuelven vacío?

Marcel Lamothe
fuente

Respuestas:

760

Todos los delegados de Func devuelven algo; Todos los delegados de acción vuelven sin efecto.

Func<TResult> no toma argumentos y devuelve TResult:

public delegate TResult Func<TResult>()

Action<T> toma un argumento y no devuelve un valor:

public delegate void Action<T>(T obj)

Action es el delegado 'simple' más simple:

public delegate void Action()

También hay Func<TArg1, TResult>y Action<TArg1, TArg2>(y otros hasta 16 argumentos). Todos estos (excepto Action<T>) son nuevos en .NET 3.5 (definido en System.Core).

Jason
fuente
11
Para su información, la próxima versión de la biblioteca de clases base incluirá tipos Func y Action que admitan más de cuatro parámetros formales. No recuerdo exactamente cuán grandes se vuelven.
Eric Lippert
88
En .NET 4.0 ahora van hasta 8 parámetros. Si siguen así, ¡en la próxima versión subirán a las once! ¡11!
Michiel van Oosterhout
99
En realidad, parece que van hasta 16 en 4.0.
Tustin2121
77
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... esto indica claramente que el compilador tendrá que ser capaz de hacer frente a más argumentos de una función que los que tiene actualmente en algún momento en el futuro !
Chris Morgan
66
En realidad, Tustin2121 tiene razón, subieron a 16 parámetros (más un tipo de retorno en el caso de Func<,,, ... ,>) en .NET 4.0, pero los últimos ocho tipos de cada "serie" se definen en System.Core.dll, no en mscorlib.dll, así que esa sería la razón por qué michielvoo no los vio. Sin embargo, no se agregaron más Funcs o Actions en .NET versiones 4.5 y 4.5.1. ¿Esta secuencia se convertirá en A170836 o A170875 ? Manténganse al tanto.
Jeppe Stig Nielsen
83

... no toma argumentos y tiene un tipo de retorno nulo?

Creo que Actiones una solución a esto.

Marcel Lamothe
fuente
47

Todos los delegados de Func toman al menos un parámetro

Eso no es cierto. Todos toman al menos un argumento de tipo, pero ese argumento determina el tipo de retorno.

Entonces Func<T>no acepta parámetros y devuelve un valor. Use Actiono Action<T>cuando no desee devolver un valor.

Joel Coehoorn
fuente
27

Intenta System.Func<T>ySystem.Action

JaredPar
fuente
1
Sin embargo, no creo que el 0 arg y otras cosas existan en .Net 2.0.
Brian
1
Es extraño: Func no existe en absoluto en .Net 2.0, aunque Predicate y Action sí.
Joel Coehoorn
2
Para .NET 2.0 use el delegado MethodInvoker.
Trevor Elliott
.NET 2 también tenía (o tiene) un tipo de delegado Converter<TInput, TOutput>que era como el posterior Func<T, TResult>. Se usó en el List<>.ConvertAllmétodo que proyectaba cada elemento en un List<>sobre otro objeto, y colocaba todos los "valores de función" en un nuevo List<>. (Más tarde, a menudo se usaría Linq Selectpara eso.)
Jeppe Stig Nielsen
0

Ocasionalmente, querrá escribir un delegado para el manejo de eventos, en cuyo caso puede aprovechar System.EvenHandler<T>que acepta implícitamente un argumento de tipo objectademás del segundo parámetro del que debe derivarse EventArgs. EventHandlers volverávoid

Personalmente, esto me pareció útil durante las pruebas para crear una devolución de llamada única en un cuerpo de función.

AndyG
fuente
0

... no toma argumentos y tiene un tipo de retorno nulo?

Si está escribiendo para System.Windows.Forms, también puede usar:

public delegate void MethodInvoker()
mojmir.novak
fuente
0

Una forma muy fácil de invocar subrutinas de valor de retorno y no retorno. está utilizando Func y Action respectivamente. (ver también https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Prueba este ejemplo

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());
    }  
}
Aarón Ibañez Werthermänn
fuente
1
Gracias por este fragmento de código, que puede proporcionar una ayuda limitada e inmediata. Una explicación adecuada mejoraría en gran medida su valor a largo plazo al mostrar por qué esta es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
iBug el