Este artículo se tradujo automáticamente. Para ver el artículo en inglés, active la casilla Inglés. Además, puede mostrar el texto en inglés en una ventana emergente si mueve el puntero del mouse sobre el texto.
Traducción
Inglés

Delegado Func<TResult>

 

Publicado: noviembre de 2016

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

Espacio de nombres:   System
Ensamblado:  mscorlib (en mscorlib.dll)

public delegate TResult Func<out TResult>()

Valor devuelto

Type: TResult

Valor devuelto del método que este delegado encapsula.

Parámetros de tipo

outTResult

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

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

System_CAPS_noteNota

Hacer referencia a un método que no tiene parámetros y devuelve void (o en Visual Basic, que se declara como un Sub en lugar de como un Function), utilice la Action delegar 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 a la OutputTarget.SendToFile método a su instancia de delegado de instancia.

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 creando instancias de la Func<TResult> delegado en lugar de definir explícitamente un nuevo delegado y asignarle un método con nombre.

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 (Guía de programación de 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 una Func<T, TResult> delegado, como se muestra en el ejemplo siguiente. (Para obtener una introducción a las expresiones lambda, vea Lambda (expresiones) (Visual Basic) y Expresiones lambda (Guía de programación de 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 la interfaz genérica Func delegados. Esto permite pasar una expresión lambda como parámetro sin asignarla explícitamente a un delegado. En particular, porque muchos métodos de tipos en el System.Linq tiene espacio de nombres Func parámetros, puede pasar estos métodos una expresión lambda sin crear explícitamente instancias de un Func delegar.

Si tiene un cálculo costoso que desea ejecutar solo si realmente se necesita el resultado, puede asignar la función costosa a un Func<TResult> delegar. A continuación, se puede retrasar la ejecución de la función hasta que una propiedad que tiene acceso el valor se utiliza en una expresión. El ejemplo en la sección siguiente muestra cómo hacerlo.

En el ejemplo siguiente se muestra cómo utilizar a 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 de delegado puede almacenar una referencia a cualquier función que devuelve un valor del tipo que corresponde al parámetro de tipo de la LazyValue objeto. El LazyValue tipo también tiene un Value propiedad que se ejecuta la función (si no se ya se ha ejecutado) y devuelve el valor resultante.

El ejemplo crea 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 sólo necesitan llamar a un método. Como muestra el resultado, los dos métodos se ejecutan solo cuando el valor de cada LazyValue recupera el objeto.

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
*/    

Plataforma universal de Windows
Disponible desde 8
.NET Framework
Disponible desde 3.5
Biblioteca de clases portable
Se admite en: plataformas portátiles de .NET
Silverlight
Disponible desde 2.0
Windows Phone Silverlight
Disponible desde 7.0
Windows Phone
Disponible desde 8.1
Volver al principio
Mostrar: