Func<TResult> Delegera

Definition

Kapslar in en metod som inte har några parametrar och returnerar ett värde av den typ som anges av parametern TResult .

generic <typename TResult>
public delegate TResult Func();
public delegate TResult Func<out TResult>();
public delegate TResult Func<out TResult>() where TResult : allows ref struct;
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 

Typparametrar

TResult

Typen av returvärde för den metod som ombudet kapslar in.

Det här är en covariant-typparameter. Det innebär att du kan använda antingen den typ du angett eller en typ som är mer härledd. Mer information om kovarians och kontravarians finns i Kovarians och kontravarians i Generisk typ.

Returvärde

TResult

Returvärdet för metoden som det här ombudet kapslar in.

Exempel

I följande exempel visas hur du använder ett ombud som inte tar några parametrar. Den här koden skapar en generisk klass med namnet LazyValue som har ett fält av typen Func<TResult>. Det här ombudsfältet kan lagra en referens till alla funktioner som returnerar ett värde av den typ som motsvarar typparametern för LazyValue objektet. Typen LazyValue har också en Value egenskap som kör funktionen (om den inte redan har körts) och returnerar det resulterande värdet.

Exemplet skapar två metoder och instansierar två LazyValue objekt med lambda-uttryck som anropar dessa metoder. Lambda-uttrycken tar inte parametrar eftersom de bara behöver anropa en metod. Som utdata visar körs de två metoderna endast när värdet för varje LazyValue objekt hämtas.

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

Kommentarer

Du kan använda det här ombudet för att representera en metod som kan skickas som en parameter utan att uttryckligen deklarera ett anpassat ombud. Den inkapslade metoden måste motsvara den metodsignatur som definieras av det här ombudet. Det innebär att den inkapslade metoden inte får ha några parametrar och måste returnera ett värde.

Note

Om du vill referera till en metod som inte har några parametrar och returnerar void (unit, i F#) (eller i Visual Basic, som deklareras som en Sub i stället för som en Function), använder du Action ombud i stället.

När du använder ombudet Func<TResult> behöver du inte uttryckligen definiera ett ombud som kapslar in en parameterlös metod. Följande kod deklarerar till exempel uttryckligen ett ombud med namnet WriteMethod och tilldelar en referens till OutputTarget.SendToFile instansmetoden till dess ombudsinstans.

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

Följande exempel förenklar den här koden genom att instansiera ombudet i stället för att uttryckligen definiera ett nytt ombud och tilldela en namngiven Func<TResult> metod till den.

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

Du kan använda ombudet Func<TResult> med anonyma metoder i C#, vilket visas i följande exempel. (En introduktion till anonyma metoder finns i Anonyma metoder.)

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

Du kan också tilldela ett lambda-uttryck till ett Func<T,TResult> ombud, vilket visas i följande exempel. (En introduktion till lambda-uttryck finns i Lambda-uttryck (VB), Lambda-uttryck (C#)och Lambda-uttryck (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

Den underliggande typen av ett lambda-uttryck är en av de allmänna Func ombuden. Detta gör det möjligt att skicka ett lambda-uttryck som en parameter utan att uttryckligen tilldela det till ett ombud. Eftersom många typer av typer i System.Linq namnområdet har Func parametrar kan du skicka dessa metoder till ett lambda-uttryck utan att uttryckligen instansiera ett Func ombud.

Om du har en dyr beräkning som du bara vill köra om resultatet faktiskt behövs kan du tilldela den dyra funktionen till ett Func<TResult> ombud. Körningen av funktionen kan sedan fördröjas tills en egenskap som har åtkomst till värdet används i ett uttryck. Exemplet i nästa avsnitt visar hur du gör detta.

Tilläggsmetoder

Name Description
GetMethodInfo(Delegate)

Hämtar ett objekt som representerar den metod som representeras av det angivna ombudet.

Gäller för

Se även