Ler em inglês

Compartilhar via


Func<TResult> Delegar

Definição

Encapsula um método que não tem parâmetros e retorna um valor do tipo especificado pelo parâmetro TResult.

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

Parâmetros de tipo

TResult

O tipo do valor retornado do método encapsulado por esse delegado.

Este parâmetro de tipo é covariante. Isso significa que é possível usar o tipo especificado ou qualquer tipo mais derivado. Para obter mais informações sobre covariância e contravariância, consulte Covariância e contravariância em genéricos.

Valor Retornado

TResult

O valor retornado do método encapsulado por esse delegado.

Exemplos

O exemplo a seguir demonstra como usar um delegado que não usa parâmetros. Esse código cria uma classe genérica chamada LazyValue que tem um campo de tipo Func<TResult>. Esse campo delegado pode armazenar uma referência a qualquer função que retorna um valor do tipo que corresponde ao parâmetro de tipo do LazyValue objeto. O LazyValue tipo também tem uma Value propriedade que executa a função (se ela ainda não foi executada) e retorna o valor resultante.

O exemplo cria dois métodos e instancia dois LazyValue objetos com expressões lambda que chamam esses métodos. As expressões lambda não tomam parâmetros porque só precisam chamar um método. Como mostra a saída, os dois métodos são executados somente quando o valor de cada LazyValue objeto é recuperado.

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

Comentários

Você pode usar esse delegado para representar um método que pode ser passado como um parâmetro sem declarar explicitamente um delegado personalizado. O método encapsulado deve corresponder à assinatura do método definida por esse delegado. Isso significa que o método encapsulado não deve ter parâmetros e deve retornar um valor.

Observação

Para fazer referência a um método que não tem parâmetros e retorna void (unitem F#) (ou em Visual Basic, que é declarado como um Sub e não como um Function), use o Action delegado em vez disso.

Quando você usa o Func<TResult> delegado, não precisa definir explicitamente um delegado que encapsula um método sem parâmetros. Por exemplo, o código a seguir declara explicitamente um delegado nomeado WriteMethod e atribui uma referência ao método de OutputTarget.SendToFile instância à instância 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;
      }
   }
}

O exemplo a seguir simplifica esse código instanciando o Func<TResult> delegado em vez de definir explicitamente um novo delegado e atribuir um método nomeado a ele.

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;
      }
   }
}

Você pode usar o Func<TResult> delegado com métodos anônimos em C#, como ilustra o exemplo a seguir. (Para obter uma introdução aos 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;
      }
   }
}

Você também pode atribuir uma expressão lambda a um Func<T,TResult> delegado, como ilustra o exemplo a seguir. (Para obter uma introdução às expressões lambda, consulte Expressões Lambda (VB), Expressões Lambda (C#)e Expressões 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;
      }
   }
}

O tipo subjacente de uma expressão lambda é um dos delegados genéricos Func . Isso possibilita passar uma expressão lambda como um parâmetro sem atribuí-la explicitamente a um delegado. Em particular, como muitos métodos de tipos no System.Linq namespace têm Func parâmetros, você pode passar a esses métodos uma expressão lambda sem instanciar explicitamente um Func delegado.

Se você tiver uma computação cara que deseja executar somente se o resultado for realmente necessário, você poderá atribuir a função cara a um Func<TResult> delegado. A execução da função pode ser atrasada até que uma propriedade que acessa o valor seja usada em uma expressão. O exemplo na próxima seção demonstra como fazer isso.

Métodos de Extensão

GetMethodInfo(Delegate)

Obtém um objeto que representa o método representado pelo delegado especificado.

Aplica-se a

Produto Versões
.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

Confira também