Func<TResult> 代理人
定義
重要
一部の情報は、リリース前に大きく変更される可能性があるプレリリースされた製品に関するものです。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。
パラメーターを持たず、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
型パラメーター
- TResult
このデリゲートによってカプセル化されるメソッドの戻り値の型。
この型パラメーターは共変です。 つまり、指定した型、または強い派生型のいずれかを使用することができます。 共変性および反変性の詳細については、「ジェネリックの共変性と反変性」をご覧ください。戻り値
- TResult
このデリゲートによってカプセル化されるメソッドの戻り値。
例
次の例では、パラメーターを受け取らないデリゲートを使用する方法を示します。 このコードでは、型のフィールドを持つ名前 LazyValue
のジェネリック クラスを作成します Func<TResult>。 このデリゲート フィールドは、オブジェクトの型パラメーターに対応する型の値を返す任意の関数への参照を LazyValue
格納できます。 型 LazyValue
には、関数を Value
実行し (まだ実行されていない場合)、結果の値を返すプロパティもあります。
この例では、2 つのメソッドを作成し、これらのメソッドを呼び出すラムダ式を使用して 2 つの LazyValue
オブジェクトをインスタンス化します。 ラムダ式は、単にメソッドを呼び出す必要があるため、パラメーターを受け取りません。 出力が示すように、2 つのメソッドは、各 LazyValue
オブジェクトの値が取得された場合にのみ実行されます。
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
注釈
このデリゲートを使用すると、カスタム デリゲートを明示的に宣言せずにパラメーターとして渡すことができるメソッドを表すことができます。 カプセル化されたメソッドは、このデリゲートによって定義されるメソッド シグネチャに対応している必要があります。 つまり、カプセル化されたメソッドにはパラメーターがなく、値を返す必要があります。
注意
パラメーターを持たず、(void
F#では) (unit
または Visual Basicでは、代わりにデリゲートとしてSub
宣言されている) メソッドをFunction
参照するには、代わりにデリゲートをAction使用します。
デリゲートを Func<TResult> 使用する場合、パラメーターなしのメソッドをカプセル化するデリゲートを明示的に定義する必要はありません。 たとえば、次のコードでは、名前付きの WriteMethod
デリゲートを明示的に宣言し、そのデリゲート インスタンスにインスタンス メソッドへの OutputTarget.SendToFile
参照を割り当てます。
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
次の例では、新しいデリゲートを明示的に定義して名前付きメソッドを Func<TResult> 割り当てるのではなく、デリゲートをインスタンス化することで、このコードを簡略化します。
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
次の例に Func<TResult> 示すように、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;
}
}
}
次の例に示すように、ラムダ式をデリゲートに Func<T,TResult> 割り当てることもできます。 (ラムダ式の概要については、「ラムダ式 (VB)、ラムダ式 (C#)、ラムダ式 (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
ラムダ式の基になる型は、ジェネリック Func
デリゲートの 1 つです。 これにより、ラムダ式を明示的にデリゲートに割り当てることなく、パラメーターとして渡すことができます。 特に、名前空間内 System.Linq の型の多くのメソッドには Func
パラメーターがあるため、デリゲートを明示的にインスタンス化せずにラムダ式をこれらのメソッドに Func
渡すことができます。
結果が実際に必要な場合にのみ実行する高価な計算がある場合は、高価な関数をデリゲートに Func<TResult> 割り当てることができます。 その後、値にアクセスするプロパティが式で使用されるまで、関数の実行を遅延させることができます。 次のセクションの例では、これを行う方法を示します。
拡張メソッド
GetMethodInfo(Delegate) |
指定したデリゲートによって表されるメソッドを表すオブジェクトを取得します。 |