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.Encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter.

generic <typename TResult>
public delegate TResult Func();
public delegate TResult Func<out TResult>();
public delegate TResult Func<TResult>();
type Func<'Result> = delegate of unit -> 'Result
Public Delegate Function Func(Of Out TResult)() As TResult 
Public Delegate Function Func(Of TResult)() As TResult 

Parámetros de tipo

TResult

Tipo del valor devuelto del método que este delegado encapsula.The type of the return value of the method that this delegate encapsulates.

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.The return value of the method that this delegate encapsulates.

Herencia
Func<TResult>

Ejemplos

En el ejemplo siguiente se muestra cómo usar un delegado que no toma ningún parámetro.The following example demonstrates how to use a delegate that takes no parameters. Este código crea una clase genérica denominada LazyValue que tiene un campo de tipo Func<TResult>.This code creates a generic class named LazyValue that has a field of type Func<TResult>. Este campo delegado puede almacenar una referencia a cualquier función que devuelve un valor del tipo que se corresponde con el parámetro de tipo del objeto LazyValue.This delegate field can store a reference to any function that returns a value of the type that corresponds to the type parameter of the LazyValue object. El tipo de LazyValue también tiene una propiedad Value que ejecuta la función (si aún no se ha ejecutado) y devuelve el valor resultante.The LazyValue type also has a Value property that executes the function (if it has not already been executed) and returns the resulting value.

En el ejemplo se crean dos métodos y se crean instancias de dos objetos LazyValue con expresiones lambda que llaman a estos métodos.The example creates two methods and instantiates two LazyValue objects with lambda expressions that call these methods. Las expresiones lambda no toman parámetros porque solo necesitan llamar a un método.The lambda expressions do not take parameters because they just need to call a method. Como se muestra en el resultado, los dos métodos solo se ejecutan cuando se recupera el valor de cada objeto de LazyValue.As the output shows, the two methods are executed only when the value of each LazyValue object is retrieved.

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
*/    
Public Module Func
   Public Sub Main()
      ' Note that each lambda expression has no parameters.
      Dim lazyOne As New LazyValue(Of Integer)(Function() ExpensiveOne())
      Dim lazyTwo As New LazyValue(Of Long)(Function() ExpensiveTwo("apple")) 

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

      ' Get the values of the LazyValue objects.
      Console.WriteLine(lazyOne.Value)
      Console.WriteLine(lazyTwo.Value)
   End Sub

   Public Function ExpensiveOne() As Integer
      Console.WriteLine()
      Console.WriteLine("ExpensiveOne() is executing.")
      Return 1
   End Function

   Public Function ExpensiveTwo(input As String) As Long
      Console.WriteLine() 
      Console.WriteLine("ExpensiveTwo() is executing.")
      Return input.Length
   End Function
End Module

Public Class LazyValue(Of T As Structure)
   Private val As Nullable(Of T)
   Private getValue As Func(Of T)

   ' Constructor.
   Public Sub New(func As Func(Of T))
      Me.val = Nothing
      Me.getValue = func
   End Sub

   Public ReadOnly Property Value() As T
      Get
         If Me.val Is Nothing Then
            ' Execute the delegate.
            Me.val = Me.getValue()
         End If   
         Return CType(val, T)
      End Get
   End Property
End Class

Comentarios

Puede usar este delegado para representar un método que se puede pasar como un parámetro sin declarar explícitamente un delegado personalizado.You can use this delegate to represent a method that can be passed as a parameter without explicitly declaring a custom delegate. El método encapsulado debe corresponder a la firma del método que define este delegado.The encapsulated method must correspond to the method signature that is defined by this delegate. Esto significa que el método encapsulado no debe tener ningún parámetro y debe devolver un valor.This means that the encapsulated method must have no parameters and must return a value.

Nota

Para 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 Function), use el delegado Action en su lugar.To reference a method that has no parameters and returns void (or in Visual Basic, that is declared as a Sub rather than as a Function), use the Action delegate instead.

Cuando se usa el delegado de Func<TResult>, no es necesario definir explícitamente un delegado que encapsula un método sin parámetros.When you use the Func<TResult> delegate, you do not have to explicitly define a delegate that encapsulates a parameterless method. Por ejemplo, el código siguiente declara explícitamente un delegado denominado WriteMethod y asigna una referencia al método de instancia OutputTarget.SendToFile a su instancia de delegado.For example, the following code explicitly declares a delegate named WriteMethod and assigns a reference to the OutputTarget.SendToFile instance method to its delegate instance.

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;
      }
   }
}
Imports System.IO

Delegate Function WriteMethod As Boolean

Module TestDelegate
   Public Sub Main()
      Dim output As New OutputTarget()
      Dim methodCall As WriteMethod = AddressOf output.SendToFile
      If methodCall() Then 
         Console.WriteLine("Success!")
      Else
         Console.WriteLine("File write operation failed.")
      End If      
   End Sub
End Module

Public Class OutputTarget
   Public Function SendToFile() As Boolean
      Try
         Dim fn As String = Path.GetTempFileName
         Dim sw As StreamWriter = New StreamWriter(fn)
         sw.WriteLine("Hello, World!")
         sw.Close      
         Return True
      Catch
         Return False
      End Try
   End Function
End Class

En el ejemplo siguiente se simplifica este código creando una instancia del delegado Func<TResult> en lugar de definir explícitamente un nuevo delegado y asignarle un método con nombre.The following example simplifies this code by instantiating the Func<TResult> delegate instead of explicitly defining a new delegate and assigning a named method to it.

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;
      }
   }
}
Imports System.IO

Module TestDelegate
   Public Sub Main()
      Dim output As New OutputTarget()
      Dim methodCall As Func(Of Boolean) = AddressOf output.SendToFile
      If methodCall() Then 
         Console.WriteLine("Success!")
      Else
         Console.WriteLine("File write operation failed.")
      End If      
   End Sub
End Module

Public Class OutputTarget
   Public Function SendToFile() As Boolean
      Try
         Dim fn As String = Path.GetTempFileName
         Dim sw As StreamWriter = New StreamWriter(fn)
         sw.WriteLine("Hello, World!")
         sw.Close      
         Return True
      Catch
         Return False
      End Try
   End Function
End Class

Puede usar el delegado de Func<TResult> con métodos anónimos C#en, como se muestra en el ejemplo siguiente.You can use the Func<TResult> delegate with anonymous methods in C#, as the following example illustrates. (Para obtener una introducción a los métodos anónimos, consulte métodos anónimos).(For an introduction to anonymous methods, see Anonymous Methods.)

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.You can also assign a lambda expression to a Func<T,TResult> delegate, as the following example illustrates. (Para ver una introducción a las expresiones lambda, vea expresiones lambda y expresiones lambda).(For an introduction to lambda expressions, see Lambda Expressions and Lambda Expressions.)

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;
      }
   }
}
Imports System.IO

Module TestDelegate
   Public Sub Main()
      Dim output As New OutputTarget()
      Dim methodCall As Func(Of Boolean) = Function() output.SendToFile()
      If methodCall() Then 
         Console.WriteLine("Success!")
      Else
         Console.WriteLine("File write operation failed.")
      End If      
   End Sub
End Module

Public Class OutputTarget
   Public Function SendToFile() As Boolean
      Try
         Dim fn As String = Path.GetTempFileName
         Dim sw As StreamWriter = New StreamWriter(fn)
         sw.WriteLine("Hello, World!")
         sw.Close      
         Return True
      Catch
         Return False
      End Try
   End Function
End Class

El tipo subyacente de una expresión lambda es uno de los delegados de Func genéricos.The underlying type of a lambda expression is one of the generic Func delegates. Esto hace posible pasar una expresión lambda como parámetro sin asignarla explícitamente a un delegado.This makes it possible to pass a lambda expression as a parameter without explicitly assigning it to a delegate. En concreto, dado que muchos métodos de tipos en el espacio de nombres System.Linq tienen parámetros Func, puede pasar estos métodos a una expresión lambda sin crear explícitamente una instancia de un delegado Func.In particular, because many methods of types in the System.Linq namespace have Func parameters, you can pass these methods a lambda expression without explicitly instantiating a Func delegate.

Si tiene un cálculo caro que desea ejecutar solo si el resultado es realmente necesario, puede asignar la función costosa a un Func<TResult> delegado.If you have an expensive computation that you want to execute only if the result is actually needed, you can assign the expensive function to a Func<TResult> delegate. La ejecución de la función se puede retrasar hasta que se use una propiedad que tiene acceso al valor en una expresión.The execution of the function can then be delayed until a property that accesses the value is used in an expression. En el ejemplo de la siguiente sección se muestra cómo hacerlo.The example in the next section demonstrates how to do this.

Métodos de extensión

GetMethodInfo(Delegate)

Obtiene un objeto que representa el método representado por el delegado especificado.Gets an object that represents the method represented by the specified delegate.

Se aplica a

Consulte también: