Leggere in inglese

Condividi tramite


Func<TResult> Delegato

Definizione

Incapsula un metodo che non presenta alcun parametro e restituisce un valore del tipo specificato dal parametro TResult.

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

Parametri di tipo

TResult

Tipo del valore restituito del metodo incapsulato da questo delegato.

Questo parametro di tipo è covariante, ovvero puoi usare il tipo specificato o qualsiasi tipo più derivato. Per altre informazioni sulla covarianza e la controvarianza, vedi Covarianza e controvarianza nei generics.

Valore restituito

TResult

Valore restituito del metodo incapsulato da questo delegato.

Esempio

Nell'esempio seguente viene illustrato come usare un delegato che non accetta parametri. Questo codice crea una classe generica denominata LazyValue con un campo di tipo Func<TResult>. Questo campo delegato può archiviare un riferimento a qualsiasi funzione che restituisce un valore del tipo che corrisponde al parametro di tipo dell'oggetto LazyValue . Il LazyValue tipo ha anche una Value proprietà che esegue la funzione (se non è già stata eseguita) e restituisce il valore risultante.

L'esempio crea due metodi e crea un'istanza di due LazyValue oggetti con espressioni lambda che chiamano questi metodi. Le espressioni lambda non accettano parametri perché devono solo chiamare un metodo. Come illustrato nell'output, i due metodi vengono eseguiti solo quando viene recuperato il valore di ogni LazyValue oggetto.

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

Commenti

È possibile usare questo delegato per rappresentare un metodo che può essere passato come parametro senza dichiarare esplicitamente un delegato personalizzato. Il metodo incapsulato deve corrispondere alla firma del metodo definita da questo delegato. Ciò significa che il metodo incapsulato non deve avere parametri e deve restituire un valore.

Nota

Per fare riferimento a un metodo senza parametri e restituisce void (unit, in F#) (o in Visual Basic, dichiarato come anziché Sub come ), Functionusare invece il Action delegato .

Quando si usa il Func<TResult> delegato, non è necessario definire in modo esplicito un delegato che incapsula un metodo senza parametri. Ad esempio, il codice seguente dichiara in modo esplicito un delegato denominato WriteMethod e assegna un riferimento al metodo di istanza all'istanza OutputTarget.SendToFile del delegato.

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

L'esempio seguente semplifica questo codice creando un'istanza del Func<TResult> delegato anziché definendo in modo esplicito un nuovo delegato e assegnando un metodo denominato.

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

È possibile usare il Func<TResult> delegato con metodi anonimi in C#, come illustrato nell'esempio seguente. Per un'introduzione ai metodi anonimi, vedere Metodi anonimi.

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

È anche possibile assegnare un'espressione lambda a un Func<T,TResult> delegato, come illustrato nell'esempio seguente. Per un'introduzione alle espressioni lambda, vedere Espressioni lambda (VB), Espressioni lambda (C#) ed Espressioni 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;
      }
   }
}

Il tipo sottostante di un'espressione lambda è uno dei delegati generici Func . In questo modo è possibile passare un'espressione lambda come parametro senza assegnarla in modo esplicito a un delegato. In particolare, poiché molti metodi di tipi nello spazio dei System.Linq nomi hanno Func parametri, è possibile passare questi metodi a un'espressione lambda senza creare esplicitamente un'istanza di un Func delegato.

Se si dispone di un calcolo costoso che si vuole eseguire solo se il risultato è effettivamente necessario, è possibile assegnare la funzione costosa a un Func<TResult> delegato. L'esecuzione della funzione può quindi essere ritardata fino a quando non viene utilizzata una proprietà che accede al valore in un'espressione. L'esempio nella sezione successiva illustra come eseguire questa operazione.

Metodi di estensione

GetMethodInfo(Delegate)

Ottiene un oggetto che rappresenta il metodo rappresentato dal delegato specificato.

Si applica a

Prodotto Versioni
.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

Vedi anche