Func<TResult> Delegat

Definicja

Hermetyzuje metodę, która nie ma parametrów i zwraca wartość typu określonego TResult przez parametr .

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

Parametry typu

TResult

Typ zwracanej wartości metody, którą hermetyzuje ten delegat.

Ten parametr typu jest kowariantny. Oznacza to, że możesz użyć typu, który został przez Ciebie określony, lub dowolnego typu, który jest bardziej pochodny. Aby uzyskać więcej informacji o kowariancji i kontrawariancji, zobacz Kowariancja i kontrawariancja w typach ogólnych.

Wartość zwracana

TResult

Zwracana wartość metody, którą hermetyzuje ten delegat.

Przykłady

W poniższym przykładzie pokazano, jak używać delegata, który nie przyjmuje żadnych parametrów. Ten kod tworzy klasę ogólną o nazwie LazyValue , która ma pole typu Func<TResult>. To pole delegata może przechowywać odwołanie do dowolnej funkcji, która zwraca wartość typu odpowiadającego parametrowi LazyValue typu obiektu. Typ LazyValue ma Value również właściwość, która wykonuje funkcję (jeśli nie została jeszcze wykonana) i zwraca wartość wynikową.

W przykładzie tworzone są dwie metody i tworzy wystąpienia dwóch LazyValue obiektów za pomocą wyrażeń lambda, które nazywają te metody. Wyrażenia lambda nie przyjmują parametrów, ponieważ wystarczy wywołać metodę. Jak pokazują dane wyjściowe, dwie metody są wykonywane tylko wtedy, gdy zostanie pobrana wartość każdego LazyValue obiektu.

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

Uwagi

Tego delegata można użyć do reprezentowania metody, którą można przekazać jako parametr bez jawnego deklarowania delegata niestandardowego. Hermetyzowana metoda musi odpowiadać podpisowi metody zdefiniowanej przez ten delegat. Oznacza to, że hermetyzowana metoda nie musi mieć parametrów i musi zwrócić wartość.

Uwaga

Aby odwołać się do metody, która nie ma parametrów i zwraca void (w języku F#) (unitlub w Visual Basic, która jest zadeklarowana jako a Sub nie jako ), należy zamiast tego użyć delegataFunctionAction.

Jeśli używasz delegata Func<TResult> , nie musisz jawnie definiować delegata, który hermetyzuje metodę bez parametrów. Na przykład poniższy kod jawnie deklaruje delegata o nazwie WriteMethod i przypisuje odwołanie do OutputTarget.SendToFile metody wystąpienia do jego wystąpienia delegowanego.

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

Poniższy przykład upraszcza ten kod przez utworzenie wystąpienia delegata Func<TResult> zamiast jawnego zdefiniowania nowego delegata i przypisania do niego nazwanej metody.

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

Delegata można używać Func<TResult> z metodami anonimowymi w języku C#, jak pokazano w poniższym przykładzie. (Aby zapoznać się z wprowadzeniem do metod anonimowych, zobacz Metody anonimowe).

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

Można również przypisać wyrażenie lambda do delegata Func<T,TResult> , jak pokazano w poniższym przykładzie. (Aby zapoznać się z wprowadzeniem do wyrażeń lambda, zobacz Wyrażenia lambda (VB), Wyrażenia lambda (C#) i Wyrażenia 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;
      }
   }
}

Podstawowym typem wyrażenia lambda jest jeden z delegatów ogólnych Func . Dzięki temu można przekazać wyrażenie lambda jako parametr bez jawnego przypisania go do delegata. W szczególności, ponieważ wiele metod typów w System.Linq przestrzeni nazw ma Func parametry, można przekazać te metody wyrażenie lambda bez jawnego utworzenia wystąpienia delegata Func .

Jeśli masz kosztowne obliczenia, które chcesz wykonać tylko wtedy, gdy wynik jest rzeczywiście potrzebny, możesz przypisać kosztowną funkcję do delegata Func<TResult> . Wykonanie funkcji można następnie opóźnić do momentu użycia właściwości, która uzyskuje dostęp do wartości w wyrażeniu. W przykładzie w następnej sekcji pokazano, jak to zrobić.

Metody rozszerzania

GetMethodInfo(Delegate)

Pobiera obiekt reprezentujący metodę reprezentowaną przez określonego delegata.

Dotyczy

Produkt Wersje
.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

Zobacz też