Action
私は .NET でとを使用する方法を知っていますが、使いFunc
始めるたびに、代わりに呼び出す通常の古いメソッドを使用してまったく同じソリューションを実現できます。
これは、LINQ の など、私が制御できないものの引数としてAction
orが使用されている場合を除外します。 Func
.Where
基本的に私の質問は...なぜこれらが存在するのですか?単純なメソッドでは得られない、余分で新しいものは何ですか?
Action と Func は、フレームワークが提供するデリゲート型です。デリゲートを使用すると、関数を変数のように扱うことができます。つまり、(とりわけ) メソッドからメソッドへ関数を渡すことができます。C++ でプログラミングしたことがある場合、デリゲートは、参照するメソッドのシグネチャによって制限される関数ポインターと考えることができます。
Action と Func は特に、いくつかの最も一般的なシグネチャを持つジェネリック デリゲート (型パラメーターを取ることを意味します) です。ほとんどのプログラムのほとんどすべてのメソッドは、これら 2 つのいずれかを使用して表すことができるため、次のようなデリゲートを手動で定義する時間を大幅に節約できます。バージョン 2 より前の .net で行っていました。実際、プロジェクトでこのようなコードを見ると、通常、プロジェクトが .net 1.1 から移行されたと安全に推測できます。
// This defines a delegate (a type that represents a function)
// but usages could easily be replaced with System.Action<String>
delegate void SomeApplicationSpecificName(String someArgument);
デリゲートについてもう少し調べることをお勧めします。これらは、C# 言語の非常に強力な機能です。
それらを使用して、関数の配列を作成します。たとえば、実行できるアクションでいっぱいの ComboBox があるとします。ComboBox にクラスまたは構造の項目を設定します。
public class ComboBoxAction
{
private string text;
private Action method;
public ComboBoxAction(string text, Action method)
{
this.text = text;
this.method = method;
}
public override string ToString()
{
return this.text;
}
public void Go()
{
this.method();
}
}
次に、誰かがアイテムを選択すると、アクションを呼び出すことができます。
CType(ComboBox1.SelectedItem, ComboBoxAction).Go()
これは、ComboBox のテキストに基づいて呼び出すメソッドを Select ステートメントで決定するよりもはるかに簡単です。
メソッドが役に立たないところで Func が役立つケースはたくさんあります。
public void DoThing(MyClass foo, Func<MyClass, string> func)
{
foo.DoSomething;
var result = func(foo);
foo.DoStringThing(result);
}
したがって、このメソッドを呼び出すときはいつでも別の Func を指定できます。DoThing
メソッドは、何が行われているかを知る必要はありません。それが何であれ、文字列を返すだけです。
delegate
代わりにキーワードを使用すると、Func キーワードを使用せずにこれを行うことができます。それはほとんど同じように機能します。
メソッドが何であるかに関係なく、(メソッドの前または後に) 何らかの操作を実行する必要がある場合に、 action
andを使用するのが最適です。func
たとえば、例外が発生した場合、メソッドを 10 回再試行する必要があります。
次のメソッドを考えてみましょう。その戻り値の型はgeneric
です。func
したがって、任意の戻り値の型に適用できます。
public static T ExecuteMultipleAttempts<T>(Func<T> inputMethod, Action additionalTask, int wait, int numOfTimes)
{
var funcResult = default(T);
int counter = 0;
while (counter < numOfTimes)
{
try
{
counter++;
funcResult = inputMethod();
//If no exception so far, the next line will break the loop.
break;
}
catch (Exception ex)
{
if (counter >= numOfTimes)
{
//If already exceeded the number of attemps, throw exception
throw;
}
else
{
Thread.Sleep(wait);
}
if (additionalTask != null)
{
additionalTask();
}
}
}
return funcResult;
}