C#3のLambda構文を使用すると、ワンライナーの無名メソッドを作成するのに非常に便利です。これらは、C#2が提供してくれたより言葉の多い匿名デリゲート構文を確実に改善したものです。ただし、ラムダの利便性は、ラムダが提供する関数型プログラミングのセマンティクスを必ずしも必要としない場所でラムダを使用したいという誘惑をもたらします。
たとえば、私のイベントハンドラーは、状態値を設定したり、別の関数を呼び出したり、別のオブジェクトにプロパティを設定したりする単純なワンライナーである(または少なくとも最初は)ことがよくあります。私のクラスにはさらに別の単純な関数がありますか、それともコンストラクターのイベントにラムダを詰め込む必要がありますか?
このシナリオでは、ラムダには明らかな欠点がいくつかあります。
- イベントハンドラーを直接呼び出すことはできません。イベントによってのみトリガーできます。もちろん、これらの単純なイベントハンドラーの場合、直接呼び出す必要がある時間はほとんどありません。
- イベントからハンドラーのフックを解除できません。一方、イベントハンドラーのフックを解除する必要があることはめったにないので、とにかく、これはそれほど問題にはなりません。
述べられた理由のために、これらの2つのことは私をあまり気にしません。そして、ラムダをメンバーデリゲートに格納することで、これらの問題の両方が本当に問題である場合は解決できますが、ラムダを便利に使用し、クラスを乱雑にしないという目的に反することになります。
他に2つのことがありますが、それほど明白ではないかもしれませんが、おそらくもっと問題があると思います。
各ラムダ関数は、それを含むスコープに対してクロージャーを形成します。これは、コンストラクターで以前に作成された一時オブジェクトが、それらへの参照を維持するクロージャのために、必要以上に長く存続することを意味する可能性があります。うまくいけば、コンパイラはラムダが使用しないクロージャからオブジェクトを除外するのに十分賢いですが、私にはわかりません。誰か知っていますか?
幸いなことに、コンストラクターで一時オブジェクトを作成することはあまりないため、これが常に問題になるとは限りません。ただし、私が行ったシナリオと、ラムダの外で簡単にスコープを設定できないシナリオを想像することができます。
- 保守性が低下する可能性があります。ビッグタイム。関数として定義されているイベントハンドラーとラムダとして定義されているイベントハンドラーがある場合、バグの追跡やクラスの理解が難しくなるのではないかと心配しています。その後、イベントハンドラーが拡張された場合は、それらをクラスレベルの関数に移動するか、コンストラクターにクラスの機能を実装するコードが大量に含まれているという事実に対処する必要があります。 。
ですから、他の人、おそらく関数型プログラミング機能を備えた他の言語の経験を持つ人のアドバイスと経験を利用したいと思います。この種のことについて確立されたベストプラクティスはありますか?イベントハンドラーで、またはラムダがその囲んでいるスコープよりも大幅に長生きするその他の場合にラムダを使用することを避けますか?そうでない場合、ラムダの代わりに実際の関数を使用することを決定するしきい値はどれですか?上記の落とし穴のいずれかが誰かを著しく噛んだことがありますか?思いもよらなかった落とし穴はありますか?