C# te permite pasar métodos como parámetros a funciones, mejorando significativamente la flexibilidad y la reutilización del código. Esta capacidad es fundamental para implementar devoluciones de llamada, controladores de eventos y patrones estratégicos donde el comportamiento en tiempo de ejecución dicta la acción específica. Este artículo explora diversos enfoques para lograr esto, centrándose en delegados personalizados, Func<>
y Action<>
.
Tabla de contenido
- Usando delegados personalizados para pasar métodos como parámetros
- Aprovechando el delegado
Func<>
- Utilizando el delegado
Action<>
- Conclusión
Usando delegados personalizados para pasar métodos como parámetros
Los delegados en C# actúan como punteros a funciones con seguridad de tipos. Crear un delegado personalizado ofrece un control granular y claridad cuando la firma del método se desvía de los delegados integrados Func<>
o Action<>
. Considere una función que realiza una operación en un número y luego muestra el resultado, donde la operación en sí es un parámetro.
// Definir un 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); // Salida: Resultado: 25
PerformOperationAndPrint(5, Cube); // Salida: Resultado: 125
}
}
MathOperation
actúa como un delegado que representa un método que acepta un double
y devuelve un double
. PerformOperationAndPrint
acepta este delegado, permitiendo el uso de Square
, Cube
o cualquier método conforme.
Aprovechando el delegado Func<>
Func<>
es un delegado genérico que representa un método con cero o más parámetros de entrada y un valor de retorno. Su naturaleza integrada simplifica muchos escenarios. Refactoricemos el ejemplo 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); // Salida: Resultado: 25
PerformOperationAndPrint(5, Cube); // Salida: Resultado: 125
}
}
Esto logra el mismo resultado con menos código. Func<double, double>
especifica un método que acepta un double
y devuelve un double
. Los parámetros de tipo genérico se adaptan a varias firmas de método (por ejemplo, Func<int, string>
).
Utilizando el delegado Action<>
Action<>
es un delegado genérico para métodos con cero o más parámetros de entrada y un tipo de retorno void
(sin valor de retorno). Úselo cuando los métodos no devuelven 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("Hola, mundo!", PrintMessage); // Salida: Hola, mundo!
PerformAction("Hola, mundo!", PrintMessageToUpper); // Salida: HOLA, MUNDO!
}
}
Action<string>
representa un método que acepta una cadena y no devuelve nada. PerformAction
utiliza esto para ejecutar varias acciones de impresión.
Conclusión
Pasar métodos como parámetros es una característica poderosa de C#. Los delegados personalizados ofrecen el máximo control, mientras que Func<>
y Action<>
proporcionan soluciones integradas convenientes. El mejor enfoque depende de los requisitos específicos de su aplicación. Dominar estas técnicas es clave para escribir código C# más adaptable y mantenible.