Func<TResult> Delegato
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Incapsula un metodo che non presenta alcun parametro e restituisce un valore del tipo specificato dal parametro TResult
.
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
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.
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
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 ), Function
usare 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.
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
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.
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
È 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.
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#).)
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
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. |