英語で読む

次の方法で共有


Func<TResult> 代理人

定義

パラメーターを持たず、TResult パラメーターで指定された型の値を返すメソッドをカプセル化します。

C#
public delegate TResult Func<out TResult>();
C#
public delegate TResult Func<TResult>();

型パラメーター

TResult

このデリゲートによってカプセル化されるメソッドの戻り値の型。

この型パラメーターは共変です。 つまり、指定した型、または強い派生型のいずれかを使用することができます。 共変性および反変性の詳細については、「ジェネリックの共変性と反変性」をご覧ください。

戻り値

TResult

このデリゲートによってカプセル化されるメソッドの戻り値。

次の例では、パラメーターを受け取らないデリゲートを使用する方法を示します。 このコードでは、型のフィールドを持つ名前 LazyValue のジェネリック クラスを作成します Func<TResult>。 このデリゲート フィールドは、オブジェクトの型パラメーターに対応する型の値を返す任意の関数への参照を LazyValue 格納できます。 型 LazyValue には、関数を Value 実行し (まだ実行されていない場合)、結果の値を返すプロパティもあります。

この例では、2 つのメソッドを作成し、これらのメソッドを呼び出すラムダ式を使用して 2 つの LazyValue オブジェクトをインスタンス化します。 ラムダ式は、単にメソッドを呼び出す必要があるため、パラメーターを受け取りません。 出力が示すように、2 つのメソッドは、各 LazyValue オブジェクトの値が取得された場合にのみ実行されます。

C#
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
*/

注釈

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

注意

パラメーターを持たず、(voidF#では) (unitまたは Visual Basicでは、代わりにデリゲートとしてSub宣言されている) メソッドをFunction参照するには、代わりにデリゲートをAction使用します。

デリゲートを Func<TResult> 使用する場合、パラメーターなしのメソッドをカプセル化するデリゲートを明示的に定義する必要はありません。 たとえば、次のコードでは、名前付きの WriteMethod デリゲートを明示的に宣言し、そのデリゲート インスタンスにインスタンス メソッドへの OutputTarget.SendToFile 参照を割り当てます。

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

次の例では、新しいデリゲートを明示的に定義して名前付きメソッドを Func<TResult> 割り当てるのではなく、デリゲートをインスタンス化することで、このコードを簡略化します。

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

次の例に Func<TResult> 示すように、C# の匿名メソッドでデリゲートを使用できます。 (匿名メソッドの概要については、 匿名メソッドを参照してください)。

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#)」を参照してください)。

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

ラムダ式の基になる型は、ジェネリック Func デリゲートの 1 つです。 これにより、ラムダ式を明示的にデリゲートに割り当てることなく、パラメーターとして渡すことができます。 特に、名前空間内 System.Linq の型の多くのメソッドには Func パラメーターがあるため、デリゲートを明示的にインスタンス化せずにラムダ式をこれらのメソッドに Func 渡すことができます。

結果が実際に必要な場合にのみ実行する高価な計算がある場合は、高価な関数をデリゲートに Func<TResult> 割り当てることができます。 その後、値にアクセスするプロパティが式で使用されるまで、関数の実行を遅延させることができます。 次のセクションの例では、これを行う方法を示します。

拡張メソッド

GetMethodInfo(Delegate)

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

適用対象

製品 バージョン
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7
.NET Framework 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

こちらもご覧ください