回答:
Func<T>
は、型の値を返すメソッドの定義済みデリゲート型ですT
。
つまり、この型を使用して、の値を返すメソッドを参照できますT
。例えば
public static string GetMessage() { return "Hello world"; }
このように参照できます
Func<string> f = GetMessage;
Func<T>
ですdelegate TResult Func<out TResult>()
。引数はありません。Func<T1, T2>
1つの引数を取る関数になります。
static int OneArgFunc(this string i) { return 42; }
Func<int> f = "foo".OneArgFunc;
。=)
Extension
CLRではなく、C#/ VB.Netコンパイラによってのみ読み取られる属性です。基本的に、インスタンスメソッド(静的関数とは異なります)には、0番目の「this」パラメーターが隠されています。したがって、1引数のインスタンスメソッドは、2引数の静的関数に非常に似ています。次に、ターゲットオブジェクトと関数ポインタを格納するデリゲートがあります。デリゲートは、最初の引数をターゲットに格納することも、しないこともできます。
プレースホルダーと考えてください。特定のパターンに従うが、特定の機能に関連付ける必要がないコードがある場合に非常に役立ちます。
たとえば、Enumerable.Select
拡張方法を考えてみましょう。
このメソッドは、Func<T, TResult>
具体的な関数の代わりに使用します。これにより、上記のパターンが適用されるあらゆる状況で使用できます。
たとえば、「」がありList<Person>
、リストのすべての人の名前だけが欲しいとします。私がすることができます:
var names = people.Select(p => p.Name);
または、私はすべての人の年齢が欲しいと言います:
var ages = people.Select(p => p.Age);
すぐに、2つの異なる関数(および)を使用して(を使用して)パターンを表す同じコードをどのように活用できたかを確認できます。Select
p => p.Name
p => p.Age
別の方法としてSelect
、シーケンスをスキャンして異なる種類の値を探すたびに、異なるバージョンを書き込むこともできます。上記と同じ効果を達成するには、次のものが必要です。
// Presumably, the code inside these two methods would look almost identical;
// the only difference would be the part that actually selects a value
// based on a Person.
var names = GetPersonNames(people);
var ages = GetPersonAges(people);
代理人がプレースホルダーとして機能することで、このような場合に同じパターンを何度も書き直す必要がなくなります。
Func<T1, T2, ..., Tn, Tr>
(T1、T2、...、Tn)引数を取り、Trを返す関数を表します。
たとえば、関数がある場合:
double sqr(double x) { return x * x; }
あなたはそれをある種の関数変数として保存することができます:
Func<double, double> f1 = sqr;
Func<double, double> f2 = x => x * x;
そして、sqrを使用するのとまったく同じように使用します。
f1(2);
Console.WriteLine(f2(f1(4)));
等
ただし、これはデリゲートであることを忘れないでください。より高度な情報については、ドキュメントを参照してください。
私が見つけFunc<T>
、私はニーズが「オンザフライ」でパーソナライズすることコンポーネントを作成するときに非常に便利。
この非常に単純な例を見てみましょう:PrintListToConsole<T>
コンポーネントです。
このオブジェクトのリストをコンソールに出力する非常にシンプルなオブジェクト。これを使用する開発者に出力をパーソナライズさせる必要があります。
たとえば、特定のタイプの数値フォーマットを彼に定義させたいとします。
Funcなし
まず、入力を受け取り、コンソールに出力する文字列を生成するクラスのインターフェイスを作成する必要があります。
interface PrintListConsoleRender<T> {
String Render(T input);
}
次にPrintListToConsole<T>
、以前に作成したインターフェイスを受け取り、それをリストの各要素に対して使用するクラスを作成する必要があります。
class PrintListToConsole<T> {
private PrintListConsoleRender<T> _renderer;
public void SetRenderer(PrintListConsoleRender<T> r) {
// this is the point where I can personalize the render mechanism
_renderer = r;
}
public void PrintToConsole(List<T> list) {
foreach (var item in list) {
Console.Write(_renderer.Render(item));
}
}
}
コンポーネントを使用する必要がある開発者は、次のことを行う必要があります。
インターフェースを実装する
実際のクラスを PrintListToConsole
class MyRenderer : PrintListConsoleRender<int> {
public String Render(int input) {
return "Number: " + input;
}
}
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 };
var printer = new PrintListToConsole<int>();
printer.SetRenderer(new MyRenderer());
printer.PrintToConsole(list);
string result = Console.ReadLine();
}
}
Funcを使用すると、はるかに簡単です。
コンポーネントの内部では、タイプTの入力パラメーターを受け取り、文字列(コンソールの出力)を返す関数のインターフェースFunc<T,String>
を表すタイプのパラメーターを定義します。
class PrintListToConsole<T> {
private Func<T, String> _renderFunc;
public void SetRenderFunc(Func<T, String> r) {
// this is the point where I can set the render mechanism
_renderFunc = r;
}
public void Print(List<T> list) {
foreach (var item in list) {
Console.Write(_renderFunc(item));
}
}
}
開発者がコンポーネントを使用する場合、コンポーネントのFunc<T, String>
型の実装を単にコンポーネントに渡します。これは、コンソールの出力を作成する関数です。
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 }; // should be a list as the method signature expects
var printer = new PrintListToConsole<int>();
printer.SetRenderFunc((o) => "Number:" + o);
printer.Print(list);
string result = Console.ReadLine();
}
}
Func<T>
その場でジェネリックメソッドインターフェイスを定義できます。
入力のタイプと出力のタイプを定義します。シンプルで簡潔。
これは、事前定義された汎用デリゲートです。それを使用すると、すべてのデリゲートを宣言する必要はありません。別の定義済みデリゲートがありAction<T, T2...>
ます。これは同じですが、voidを返します。
情報を追加するのに遅すぎることはないでしょう。
和:
Funcは、システムネームスペースで定義されたカスタムデリゲートであり、0〜16の入力パラメーターを使用して同じデリゲート(デリゲートと同じ)を持つメソッドを指すことができ、何かを返す必要があります。
命名法と使用方法:
Func<input_1, input_2, ..., input1_6, output> funcDelegate = someMethod;
定義:
public delegate TResult Func<in T, out TResult>(T arg);
使用場所:
ラムダ式と無名メソッドで使用されます。