Leer en inglés

Compartir a través de


Func<TResult> Delegado

Definición

Encapsula un método que no tiene parámetros y devuelve un valor del tipo especificado por el parámetro TResult.

C#
public delegate TResult Func<out TResult>();
C#
public delegate TResult Func<TResult>();

Parámetros de tipo

TResult

Tipo del valor devuelto del método que este delegado encapsula.

Este parámetro de tipo es covariante, es decir, puede usar el tipo que haya especificado o cualquier tipo más derivado. Si desea obtener más información sobre la covarianza y la contravarianza, consulte Covarianza y contravarianza en genéricos.

Valor devuelto

TResult

Valor devuelto del método que este delegado encapsula.

Ejemplos

En el ejemplo siguiente se muestra cómo usar un delegado que no toma ningún parámetro. Este código crea una clase genérica denominada LazyValue que tiene un campo de tipo Func<TResult>. Este campo delegado puede almacenar una referencia a cualquier función que devuelva un valor del tipo que corresponde al parámetro type del LazyValue objeto. El LazyValue tipo también tiene una Value propiedad que ejecuta la función (si aún no se ha ejecutado) y devuelve el valor resultante.

En el ejemplo se crean dos métodos y se crean instancias de dos LazyValue objetos con expresiones lambda que llaman a estos métodos. Las expresiones lambda no toman parámetros porque solo necesitan llamar a un método . Como se muestra en la salida, los dos métodos solo se ejecutan cuando se recupera el valor de cada LazyValue objeto.

C#
using System;

static class Func1
{
   public static void Main()
   {
      // Note that each lambda expression has no parameters.
      LazyValue<int> lazyOne = new LazyValue<int>(() => ExpensiveOne());
      LazyValue<long> lazyTwo = new LazyValue<long>(() => ExpensiveTwo("apple"));

      Console.WriteLine("LazyValue objects have been created.");

      // Get the values of the LazyValue objects.
      Console.WriteLine(lazyOne.Value);
      Console.WriteLine(lazyTwo.Value);
   }

   static int ExpensiveOne()
   {
      Console.WriteLine("\nExpensiveOne() is executing.");
      return 1;
   }

   static long ExpensiveTwo(string input)
   {
      Console.WriteLine("\nExpensiveTwo() is executing.");
      return (long)input.Length;
   }
}

class LazyValue<T> where T : struct
{
   private Nullable<T> val;
   private Func<T> getValue;

   // Constructor.
   public LazyValue(Func<T> func)
   {
      val = null;
      getValue = func;
   }

   public T Value
   {
      get
      {
         if (val == null)
            // Execute the delegate.
            val = getValue();
         return (T)val;
      }
   }
}
/* The example produces the following output:

    LazyValue objects have been created.

    ExpensiveOne() is executing.
    1

    ExpensiveTwo() is executing.
    5
*/

Comentarios

Puede usar este delegado para representar un método que se puede pasar como parámetro sin declarar explícitamente un delegado personalizado. El método encapsulado debe corresponder a la firma del método definida por este delegado. Esto significa que el método encapsulado no debe tener parámetros y debe devolver un valor.

Nota

Para hacer referencia a un método que no tiene parámetros y devuelve void (unit, en F#) (o en Visual Basic, que se declara como en Sub lugar de como Function), use el Action delegado en su lugar.

Cuando se usa el Func<TResult> delegado, no es necesario definir explícitamente un delegado que encapsula un método sin parámetros. Por ejemplo, el código siguiente declara explícitamente un delegado denominado WriteMethod y asigna una referencia al OutputTarget.SendToFile método de instancia a su instancia delegada.

C#
using System;
using System.IO;

delegate bool WriteMethod();

public class TestDelegate
{
   public static void Main()
   {
      OutputTarget output = new OutputTarget();
      WriteMethod methodCall = output.SendToFile;
      if (methodCall())
         Console.WriteLine("Success!");
      else
         Console.WriteLine("File write operation failed.");
   }
}

public class OutputTarget
{
   public bool SendToFile()
   {
      try
      {
         string fn = Path.GetTempFileName();
         StreamWriter sw = new StreamWriter(fn);
         sw.WriteLine("Hello, World!");
         sw.Close();
         return true;
      }
      catch
      {
         return false;
      }
   }
}

En el ejemplo siguiente se simplifica este código mediante la creación de instancias del Func<TResult> delegado en lugar de definir explícitamente un nuevo delegado y asignarle un método con nombre.

C#
using System;
using System.IO;

public class TestDelegate
{
   public static void Main()
   {
      OutputTarget output = new OutputTarget();
      Func<bool> methodCall = output.SendToFile;
      if (methodCall())
         Console.WriteLine("Success!");
      else
         Console.WriteLine("File write operation failed.");
   }
}

public class OutputTarget
{
   public bool SendToFile()
   {
      try
      {
         string fn = Path.GetTempFileName();
         StreamWriter sw = new StreamWriter(fn);
         sw.WriteLine("Hello, World!");
         sw.Close();
         return true;
      }
      catch
      {
         return false;
      }
   }
}

Puede usar el Func<TResult> delegado con métodos anónimos en C#, como se muestra en el ejemplo siguiente. (Para obtener una introducción a los métodos anónimos, consulte Métodos anónimos).

C#
using System;
using System.IO;

public class Anonymous
{
   public static void Main()
   {
      OutputTarget output = new OutputTarget();
      Func<bool> methodCall = delegate() { return output.SendToFile(); };
      if (methodCall())
         Console.WriteLine("Success!");
      else
         Console.WriteLine("File write operation failed.");
   }
}

public class OutputTarget
{
   public bool SendToFile()
   {
      try
      {
         string fn = Path.GetTempFileName();
         StreamWriter sw = new StreamWriter(fn);
         sw.WriteLine("Hello, World!");
         sw.Close();
         return true;
      }
      catch
      {
         return false;
      }
   }
}

También puede asignar una expresión lambda a un Func<T,TResult> delegado, como se muestra en el ejemplo siguiente. (Para obtener una introducción a las expresiones lambda, vea Expresiones lambda (VB), Expresiones lambda (C#) y Expresiones lambda (F#)).

C#
using System;
using System.IO;

public class Anonymous
{
   public static void Main()
   {
      OutputTarget output = new OutputTarget();
      Func<bool> methodCall = () => output.SendToFile();
      if (methodCall())
         Console.WriteLine("Success!");
      else
         Console.WriteLine("File write operation failed.");
   }
}

public class OutputTarget
{
   public bool SendToFile()
   {
      try
      {
         string fn = Path.GetTempFileName();
         StreamWriter sw = new StreamWriter(fn);
         sw.WriteLine("Hello, World!");
         sw.Close();
         return true;
      }
      catch
      {
         return false;
      }
   }
}

El tipo subyacente de una expresión lambda es uno de los delegados genéricos Func . Esto permite pasar una expresión lambda como un parámetro sin asignarla explícitamente a un delegado. En concreto, dado que muchos métodos de tipos del System.Linq espacio de nombres tienen Func parámetros, puede pasar estos métodos a una expresión lambda sin crear instancias explícitas de un Func delegado.

Si tiene un cálculo costoso que desea ejecutar solo si el resultado es realmente necesario, puede asignar la función costosa a un Func<TResult> delegado. La ejecución de la función se puede retrasar hasta que se use una propiedad que tenga acceso al valor en una expresión. En el ejemplo de la sección siguiente se muestra cómo hacerlo.

Métodos de extensión

GetMethodInfo(Delegate)

Obtiene un objeto que representa el método representado por el delegado especificado.

Se aplica a

Producto Versiones
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7
.NET Framework 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Consulte también