25

これが基本的なものである場合は申し訳ありませんが、私は.Net3.5でピックアップしようとしていました。

質問:Func <>について何か素晴らしいことはありますか?それは5つのオーバーロードですか?その見た目から、正確に5つのオーバーロードとそれ以上のオーバーロードを使用して、MyFunc<>という同様のデルゲートを自分で作成できます。

例:public delegate TResult MyFunc<TResult>()およびさまざまなオーバーロードの組み合わせ..

Func <>の代表者を理解しようとして、次のシナリオを思いついたときに、この考えが浮かびました。

Func<int,int> myDelegate = (y) => IsComposite(10);

これは、int型の1つのパラメーターとint型の戻り型を持つデリゲートを意味します。5つのバリエーションがあります(インテリセンスによるオーバーロードを見る場合)。だから私は、リターンタイプのないデリゲートを持つことができると推測していますか?

では、Func <>は素晴らしいものではなく、.Net Frameworkの単なる例であり、必要に応じて、独自のニーズに合わせてカスタムの「func <>」デリゲートを作成できると言っても過言ではありませんか?

ありがとう、

4

6 に答える 6

64

偉大さは、より良いコミュニケーションのために共有言語を確立することにあります。

同じこと (デリゲートの爆発) に対して独自のデリゲート タイプを定義する代わりに、フレームワークによって提供されるものを使用します。あなたのコードを読んだ人は誰でも、あなたが達成しようとしていることを即座に把握できます..「このコードは実際に何をしているのか?」という時間を最小限に抑えます。だから私が見るとすぐに

  • アクション= 何かを実行するだけで出力を返さないメソッド
  • 比較= 同じ型の 2 つのオブジェクトを比較し、順序を示すために int を返す何らかのメソッド
  • コンバーター= Obj A を同等の Obj B に変換します
  • EventHandler = イベント引数の形式で何らかの入力が与えられたオブジェクトによって発生したイベントへの応答/ハンドラー
  • Func = いくつかのパラメーターを取り、何かを計算して結果を返す何らかのメソッド
  • 述語= いくつかの基準に対して入力オブジェクトを評価し、合格/不合格ステータスを bool として返す

それが私の差し迫った関心領域でない限り、それ以上深く掘り下げる必要はありません。したがって、必要なデリゲートがこれらのニーズのいずれかに適合すると思われる場合は、独自のデリゲートを展開する前にそれらを使用してください。

免責事項: 個人的には、言語設計者によるこの動きが気に入っています。

反論: デリゲートを定義すると、意図をよりよく伝えることができる場合があります。例えばSystem.Threading.ThreadStartオーバーSystem.Action。ということで、最終的には裁判です。

于 2008-11-26T06:44:39.220 に答える
12

デリゲートのFuncファミリ (およびその戻り値の型のないいとこAction) は、.NET フレームワークで見られるものより優れているわけではありません。それらは再利用のためにあるだけなので、再定義する必要はありません。それらには、物事を汎用的に保つための型パラメーターがあります。たとえば、 Func<T0,bool> は System.Predicate<T> デリゲートと同じです。これらはもともと LINQ 用に設計されたものです。

Func名前に意図を反映させたい場合を除き、そのような目的で独自のデリゲートを定義する代わりに、最大 4 つの引数を受け入れる値を返すメソッドに組み込みのデリゲートを使用できるはずです。これは素晴らしいことです。

デリゲート型を定義する必要が絶対にあるケースには、4 つ以上の引数を受け入れるメソッド、outref、またはparamsパラメーターを持つメソッド、または再帰的なメソッド シグネチャ ( などdelegate Foo Foo(Foo f)) が含まれます。

于 2008-11-26T05:09:03.797 に答える
9

マルキシダードの正解に加えて:

  • ActionFunc に関連するファミリであるデリゲートに注意する価値があります。繰り返しますが、これらは型パラメーターの数によってオーバーロードされた型ですが、void を返すように宣言されています。
  • .NET 2.0 プロジェクトで Func/Action を使用したいが、後でアップグレードするための簡単な方法がある場合は、私のバージョン比較ページから宣言をカット アンド ペーストできます。それらをSystem名前空間で宣言すると、後で宣言を削除するだけでアップグレードできますが、宣言を削除せずに .NET 3.5 で同じコードを (簡単に) ビルドすることはできません。
于 2008-11-26T06:34:47.260 に答える
7

依存関係と邪悪な結びつきを分離することは、それを素晴らしいものにする唯一のことです. それ以外のことはすべて、自家製の方法で議論し、実行可能であると主張できます。

私は、古くて重い lib を使用して少し複雑なシステムをリファクタリングしてきましたが、「反対側」に潜んでいる名前付きデリゲートのために、コンパイル時間の依存関係を壊すことができないという理由でブロックされました。すべてのアセンブリの読み込みとリフレクションは役に立たなかった - コンパイラは単に delegate() {...} をオブジェクトにキャストすることを拒否し、それを鎮めるために何をしても反対側で失敗する.

コンパイル時に構造化されたデリゲート型比較は、その後(ロード、呼び出し) 名目になります。「私の最愛の lib は永遠に誰にでも使われるだろう」という観点から考えると、それは問題ないように思えるかもしれませんが、それは少し複雑なシステムにも拡張できません。Fun<> テンプレートは、名目上のタイピングの世界にある程度の構造的同等性をもたらします。それは、独自のロールアウトでは達成できない側面です。

例 - 変換:

class Session ( 
    public delegate string CleanBody();    // tying you up and you don't see it :-)
    public static void Execute(string name, string q, CleanBody body) ... 

に:

    public static void Execute(string name, string q, Func<string> body)

完全に独立したコードで、次のようなリフレクション呼び出しを実行できます。

Type type = Type.GetType("Bla.Session, FooSessionDll", true); 
MethodInfo methodInfo = type.GetMethod("Execute"); 

Func<string> d = delegate() { .....}  // see Ma - no tie-ups :-)
Object [] params = { "foo", "bar", d};
methodInfo.Invoke("Trial Execution :-)", params);

既存のコードは違いに気付かず、新しいコードは依存しません - 地球上の平和 :-)

于 2010-06-24T23:39:24.343 に答える
1

デリゲートについて私が気に入っていることの 1 つは、メソッド内でメソッドを宣言できることです。これは、コードの一部を再利用したいが、そのメソッド内でのみ必要な場合に便利です。ここでの目的はスコープをできるだけ限定することなので、 Func<> が便利です。

例えば:

string FormatName(string pFirstName, string pLastName) {
    Func<string, string> MakeFirstUpper = (pText) => {
        return pText.Substring(0,1).ToUpper() + pText.Substring(1);
    };

    return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}

次のようなヘルパー関数を作成すると、推論を使用できる場合はさらに簡単で便利です。

Func<T, TReturn> Lambda<T, TReturn>(Func<T, TReturn> pFunc) {
    return pFunc;
}

これで、Func<> を使用せずに関数を書き直すことができます。

string FormatName(string pFirstName, string pLastName) {
    var MakeFirstUpper = Lambda((string pText) => {
        return pText.Substring(0,1).ToUpper() + pText.Substring(1);
    });

    return MakeFirstUpper(pFirstName) + " " + MakeFirstUpper(pLastName);
}

メソッドをテストするコードは次のとおりです。

Console.WriteLine(FormatName("luis", "perez"));
于 2012-01-02T01:01:02.603 に答える
-1

これは古いスレッドですが、 func<> と action<> も共分散と反分散を使用するのに役立つことを追加する必要がありました。

http://msdn.microsoft.com/en-us/library/dd465122.aspx

于 2010-12-05T00:03:59.283 に答える