Func<TResult> Delegat

Definition

Kapselt eine Methode, die über keine Parameter verfügt und einen Wert des Typs zurückgibt, der vom TResult-Parameter angegeben wird.

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 

Typparameter

TResult

Der Typ des Rückgabewerts der Methode, die dieser Delegat kapselt.

Dieser Typparameter ist kovariant. Das bedeutet, dass Sie entweder den angegebenen Typ oder einen stärker abgeleiteten Typ verwenden können. Weitere Informationen zu Kovarianz und Kontravarianz finden Sie unter Kovarianz und Kontravarianz in Generics.

Rückgabewert

TResult

Der Rückgabewert der Methode, die dieser Delegat kapselt.

Beispiele

Im folgenden Beispiel wird veranschaulicht, wie Sie eine Stellvertretung verwenden, die keine Parameter verwendet. Dieser Code erstellt eine generische Klasse mit dem Namen LazyValue "Feld des Typs Func<TResult>". Dieses Stellvertretungsfeld kann einen Verweis auf eine beliebige Funktion speichern, die einen Wert des Typs zurückgibt, der dem Typparameter des LazyValue Objekts entspricht. Der LazyValue Typ verfügt auch über eine Value Eigenschaft, die die Funktion ausführt (wenn sie noch nicht ausgeführt wurde) und den resultierenden Wert zurückgibt.

Im Beispiel werden zwei Methoden erstellt und zwei LazyValue Objekte mit Lambdaausdrucken instanziiert, die diese Methoden aufrufen. Die Lambdaausdrücke nehmen keine Parameter, da sie nur eine Methode aufrufen müssen. Wie die Ausgabe zeigt, werden die beiden Methoden nur ausgeführt, wenn der Wert jedes LazyValue Objekts abgerufen wird.

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

type LazyValue<'T>(func: Func<'T>) =
    let mutable value = ValueNone

    member _.Value =
        match value with
        | ValueSome v -> v
        | ValueNone ->
            // Execute the delegate.
            let v = func.Invoke()
            value <- ValueSome v
            v

let expensiveOne () =
    printfn "\nExpensiveOne() is executing."
    1

let expensiveTwo (input: string) =
    printfn "\nExpensiveTwo() is executing."
    int64 input.Length

// Note that each lambda expression has no parameters.
let lazyOne = LazyValue(fun () -> expensiveOne ())
let lazyTwo = LazyValue(fun () -> expensiveTwo "apple")

printfn "LazyValue objects have been created."

// Get the values of the LazyValue objects.
printfn $"{lazyOne.Value}"
printfn $"{lazyTwo.Value}"


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

Hinweise

Sie können diese Stellvertretung verwenden, um eine Methode darzustellen, die als Parameter übergeben werden kann, ohne explizit eine benutzerdefinierte Stellvertretung zu deklarieren. Die gekapselte Methode muss der Von diesem Stellvertretung definierten Methodensignatur entsprechen. Dies bedeutet, dass die gekapselte Methode keine Parameter aufweisen muss und einen Wert zurückgeben muss.

Hinweis

Um auf eine Methode zu verweisen, die keine Parameter enthält und void zurückgibt (in F#) (unitoder in Visual Basic, das als Sub eine anstelle Functioneiner ) deklariert wird, verwenden Sie stattdessen die Action Stellvertretung.

Wenn Sie die Func<TResult> Stellvertretung verwenden, müssen Sie keine Stellvertretung explizit definieren, die eine parameterlose Methode kapselt. Der folgende Code deklariert z. B. explizit einen Stellvertretungsnamen WriteMethod und weist eine Referenz zur OutputTarget.SendToFile Instanzmethode der Stellvertretungsinstanz zu.

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

type WriteMethod = delegate of unit -> bool

type OutputTarget() =
    member _.SendToFile() =
        try
            let fn = Path.GetTempFileName()
            use sw = new StreamWriter(fn)
            sw.WriteLine "Hello, World!"
            true
        with _ ->
            false

let output = new OutputTarget()
let methodCall = WriteMethod output.SendToFile
if methodCall.Invoke() then
    printfn "Success!"
else
    printfn "File write operation failed."
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

Im folgenden Beispiel wird dieser Code vereinfacht, indem er die Stellvertretung instanziiert Func<TResult> , anstatt eine neue Stellvertretung explizit zu definieren und einer benannten Methode zuzuweisen.

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

type OutputTarget() =
    member _.SendToFile() =
        try
            let fn = Path.GetTempFileName()
            use sw = new StreamWriter(fn)
            sw.WriteLine "Hello, World!"
            true
        with _ ->
            false

let output = OutputTarget()
let methodCall = Func<bool> output.SendToFile
if methodCall.Invoke() then
    printfn "Success!"
else
    printfn "File write operation failed."
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

Sie können die Stellvertretung mit anonymen Methoden in C# verwenden, wie das Func<TResult> folgende Beispiel veranschaulicht. (Eine Einführung in anonyme Methoden finden Sie unter Anonyme Methoden.)

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

Sie können auch einem Func<T,TResult> Stellvertretung einen Lambdaausdruck zuweisen, wie das folgende Beispiel veranschaulicht. (Eine Einführung in Lambda-Ausdrücke finden Sie unter Lambda-Ausdrücke (VB), Lambda-Ausdrücke (C#) und Lambda-Ausdrücke (F#).)

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

type OutputTarget() =
    member _.SendToFile() =
        try
            let fn = Path.GetTempFileName()
            use sw = new StreamWriter(fn)
            sw.WriteLine "Hello, World!"
            true
        with _ ->
            false

let output = OutputTarget()
let methodCall = Func<bool>(fun () -> output.SendToFile())
if methodCall.Invoke() then
    printfn "Success!"
else
    printfn "File write operation failed."
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

Der zugrunde liegende Typ eines Lambdaausdrucks ist eine der generischen Func Stellvertretungen. Dadurch kann ein Lambdaausdruck als Parameter übergeben werden, ohne ihn explizit einem Stellvertretung zuzuweisen. Insbesondere, da viele Typen im System.Linq Namespace Parameter haben Func , können Sie diese Methoden einen Lambdaausdruck übergeben, ohne eine Func Stellvertretung explizit instanziieren zu müssen.

Wenn Sie über eine teure Berechnung verfügen, die Sie nur ausführen möchten, wenn das Ergebnis tatsächlich benötigt wird, können Sie die teure Funktion einem Func<TResult> Stellvertretung zuweisen. Die Ausführung der Funktion kann dann verzögert werden, bis eine Eigenschaft, die auf den Wert zugreift, in einem Ausdruck verwendet wird. Das Beispiel im nächsten Abschnitt veranschaulicht, wie Dies geschieht.

Erweiterungsmethoden

GetMethodInfo(Delegate)

Ruft ein Objekt ab, das die Methode darstellt, die vom angegebenen Delegaten dargestellt wird.

Gilt für

Siehe auch