Delegado Func sem tipo de retorno

561

Todos os delegados do Func retornam um valor. Quais são os delegados do .NET que podem ser usados ​​com métodos que retornam nulos?

Marcel Lamothe
fonte

Respostas:

760

Todos os delegados da Func retornam algo; todos os delegados da ação retornam nulos.

Func<TResult> não aceita argumentos e retorna TResult:

public delegate TResult Func<TResult>()

Action<T> recebe um argumento e não retorna um valor:

public delegate void Action<T>(T obj)

Action é o delegado mais simples e simples:

public delegate void Action()

Há também Func<TArg1, TResult>e Action<TArg1, TArg2>(e outros até 16 argumentos). Todos esses (exceto Action<T>) são novos no .NET 3.5 (definido em System.Core).

Jason
fonte
11
Para sua informação, a próxima versão da biblioteca de classes base incluirá os tipos Func e Action que suportam mais de quatro parâmetros formais. Não me lembro exatamente de quão grande eles ficam.
Eric Lippert
88
No .NET 4.0, eles agora chegam a 8 parâmetros. Se eles continuarem assim, na próxima versão ele subirá para onze !! 11 !!!
Michiel van Oosterhout 15/05
9
Na verdade, parece que eles chegam a 16 em 4.0.
precisa saber é o seguinte
7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... isso indica claramente que o compilador precisará ser capaz de lidar com mais argumentos para uma função do que atualmente em algum momento no futuro !
23412 Chris Morgan
6
Na verdade, Tustin2121 está certo, eles subiram para 16 parâmetros (mais um tipo de retorno no caso de Func<,,, ... ,>) no .NET 4.0, mas os últimos oito tipos de cada "série" são definidos em System.Core.dll, não em mscorlib.dll, portanto, esse seria o motivo porque michielvoo não os viu. No entanto, nenhum Func ou Ação foi adicionado nas versões 4.5 e 4.5.1 do .NET. Essa sequência se tornará A170836 ou A170875 ? Fique ligado.
Jeppe Stig Nielsen
83

... não aceita argumentos e tem um tipo de retorno nulo?

Eu acredito que Actioné uma solução para isso.

Marcel Lamothe
fonte
47

Todos os delegados do Func usam pelo menos um parâmetro

Isso não é verdade. Todos eles usam pelo menos um argumento de tipo, mas esse argumento determina o tipo de retorno.

Portanto, Func<T>não aceita parâmetros e retorna um valor. Use Actionou Action<T>quando não desejar retornar um valor.

Joel Coehoorn
fonte
27

Experimente System.Func<T>eSystem.Action

JaredPar
fonte
1
Eu não acho que o argumento 0 e outros enfeites existem no .Net 2.0, no entanto.
2727 Brian
1
É estranho: o Func não existe no .Net 2.0, embora Predicate e Action existam.
Joel Coehoorn
2
Para o .NET 2.0, use o delegado MethodInvoker.
Trevor Elliott
O .NET 2 também tinha (ou tem) um tipo de delegado Converter<TInput, TOutput>semelhante ao posterior Func<T, TResult>. Foi usado no List<>.ConvertAllmétodo que projetava todos os elementos de um List<>objeto em outro e colocou todos os "valores de função" em um novo List<>. (Mais tarde, seria costumam usar Linq Selectpara isso.)
Jeppe Stig Nielsen
0

Ocasionalmente, você deseja escrever um delegado para manipulação de eventos; nesse caso, você pode tirar vantagem do System.EvenHandler<T>que aceita implicitamente um argumento do tipo object, além do segundo parâmetro que deve derivar EventArgs. EventHandlers retornarávoid

Pessoalmente, achei isso útil durante o teste para criar um retorno de chamada único em um corpo de função.

AndyG
fonte
0

... não aceita argumentos e tem um tipo de retorno nulo?

Se você está escrevendo System.Windows.Forms, também pode usar:

public delegate void MethodInvoker()
mojmir.novak
fonte
0

Uma maneira muito fácil de chamar sub-rotinas de retorno e não retorno. está usando Func e Action, respectivamente. (consulte também https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Tente este exemplo

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
fonte
1
Obrigado por este trecho de código, que pode fornecer ajuda imediata e limitada. Uma explicação adequada melhoraria bastante seu valor a longo prazo , mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com outras perguntas semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
iBug