Func<TResult> 代理人

定義

パラメーターを持たず、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 つのメソッドを作成し、これらのメソッドを呼び出すラムダ式を使用して LazyValue 2 つの オブジェクトをインスタンス化します。 ラムダ式は、メソッドを呼び出す必要があるだけなので、パラメーターを受け取る必要はありません。 出力に示すように、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
*/
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

注釈

このデリゲートを使用すると、カスタム デリゲートを明示的に宣言せずにパラメーターとして渡すメソッドを表します。 カプセル化されたメソッドは、このデリゲートによって定義されるメソッド シグネチャに対応している必要があります。 つまり、カプセル化されたメソッドにはパラメーターが必要で、値を返す必要があります。

注意

パラメーターを持ち、(または Visual Basic で ではなく として宣言されている) パラメーターを返すメソッドを参照するには、代わりに デリゲートを void 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;
      }
   }
}
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;
      }
   }
}
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> デリゲートに割り当てすることもできます。 (ラムダ式の概要については、「ラムダ式とラムダ式」を参照してください)。

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

指定したデリゲートによって表されるメソッドを表すオブジェクトを取得します。

適用対象

こちらもご覧ください