C# permite que você passe métodos como parâmetros para funções, melhorando significativamente a flexibilidade e a reusabilidade do código. Essa capacidade é fundamental para implementar callbacks, manipuladores de eventos e padrões estratégicos onde o comportamento em tempo de execução dita a ação específica. Este artigo explora diferentes abordagens para alcançar isso, focando em delegados personalizados, Func<>
e Action<>
.
Sumário
- Usando Delegados Personalizados para Passar Métodos como Parâmetros
- Aproveitando o Delegado
Func<>
- Utilizando o Delegado
Action<>
- Conclusão
Usando Delegados Personalizados para Passar Métodos como Parâmetros
Delegados em C# servem como ponteiros de função com tipagem segura. Criar um delegado personalizado oferece controle granular e clareza quando a assinatura do método difere dos delegados Func<>
ou Action<>
integrados. Considere uma função que executa uma operação em um número e, em seguida, exibe o resultado, onde a própria operação é um parâmetro.
// Define um delegado personalizado
public delegate double MathOperation(double x);
public class Example
{
public static void PerformOperationAndPrint(double num, MathOperation operation)
{
double result = operation(num);
Console.WriteLine($"Resultado: {result}");
}
public static double Square(double x) => x * x;
public static double Cube(double x) => x * x * x;
public static void Main(string[] args)
{
PerformOperationAndPrint(5, Square); // Saída: Resultado: 25
PerformOperationAndPrint(5, Cube); // Saída: Resultado: 125
}
}
MathOperation
atua como um delegado representando um método que aceita um double
e retorna um double
. PerformOperationAndPrint
aceita este delegado, permitindo o uso de Square
, Cube
ou qualquer método compatível.
Aproveitando o Delegado Func<>
Func<>
é um delegado genérico que representa um método com zero ou mais parâmetros de entrada e um valor de retorno. Sua natureza integrada simplifica muitos cenários. Vamos refatorar o exemplo anterior:
public class Example
{
public static void PerformOperationAndPrint(double num, Func<double, double> operation)
{
double result = operation(num);
Console.WriteLine($"Resultado: {result}");
}
public static double Square(double x) => x * x;
public static double Cube(double x) => x * x * x;
public static void Main(string[] args)
{
PerformOperationAndPrint(5, Square); // Saída: Resultado: 25
PerformOperationAndPrint(5, Cube); // Saída: Resultado: 125
}
}
Isso alcança o mesmo resultado com menos código. Func<double, double>
especifica um método que aceita um double
e retorna um double
. Os parâmetros de tipo genérico se adaptam a várias assinaturas de método (por exemplo, Func<int, string>
).
Utilizando o Delegado Action<>
Action<>
é um delegado genérico para métodos com zero ou mais parâmetros de entrada e um tipo de retorno void
(sem valor de retorno). Use-o quando os métodos não retornarem valores.
public class Example
{
public static void PerformAction(string message, Action<string> action)
{
action(message);
}
public static void PrintMessage(string msg) => Console.WriteLine(msg);
public static void PrintMessageToUpper(string msg) => Console.WriteLine(msg.ToUpper());
public static void Main(string[] args)
{
PerformAction("Olá, mundo!", PrintMessage); // Saída: Olá, mundo!
PerformAction("Olá, mundo!", PrintMessageToUpper); // Saída: OLÁ, MUNDO!
}
}
Action<string>
representa um método que aceita uma string e não retorna nada. PerformAction
usa isso para executar várias ações de impressão.
Conclusão
Passar métodos como parâmetros é um recurso poderoso do C#. Delegados personalizados oferecem o máximo controle, enquanto Func<>
e Action<>
fornecem soluções integradas convenientes. A melhor abordagem depende dos requisitos específicos do seu aplicativo. Dominar essas técnicas é fundamental para escrever código C# mais adaptável e sustentável.