C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2009/05/23 23:28
.NET Framework 3.5 が出てきた時からずっと思っていたことなのですが、今更一言。

独自のデリゲートを定義する代わりになんでもかんでも Func デリゲートやら Action デリゲートで済ますのはやめましょう。

これらのデリゲートは汎用的に使用できるようにと定義されていますが、大きな欠点があります。それは、パラメータに名称を付けられないということです。

例えば Enumerable.Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, Int32, TResult> selector) メソッドは、Func<TSource, Int32, TResult> デリゲートを受け取ります。この Func デリゲートの第一引数はまぁ良いとして ()、第二引数は一体何の役割を持っているのでしょうか。
前述の通り、Func デリゲートではパラメータに名称を付けられないため、引数の役割はドキュメントから読み取るしかありません。
ドキュメントを読めば、シーケンス内での要素の位置を表す値であることがわかりますが、これがもし、Func デリゲートではなく次のように厳密なデリゲートだったとしたらどうでしょう。

public delegate TSource Selector<TSource>(TSource source, int index);
これならば、ドキュメントを読む前に index という名前から第二引数の役割を推測できます。しかも第二引数の詳細を知りたければ、直接このデリゲートのドキュメントを読めば済みます。

// 追記 (2009/05/24)
パラメータ名がないとドキュメントの書き方が「第一引数は○○です」なんて説明になるので、パラメータリストの順序変更などでドキュメントとの不整合が生じやすくもなります。しっかりデリゲー ト定義すれば <param> タグが使えるので、ドキュメントとの不整合もある程度コンパイラが警告してくれます。
// 追記ここまで


というわけで、Func デリゲートやら Action デリゲートを全否定するわけではないですが、これらのデリゲートは表現力が弱いということは認識しておいた方が良いと思います。



※ これに関しては Select メソッドの型パラメータ名 (TSource) によって役割を推測できます。でも Enumerable.Aggregate<TSource>(IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)  なんかだと Aggregate メソッドの型パラメータ名 (TSource) からも推測できないです。
タグ: .NET C#


全然そんなこと考えたこともなかったので、なるほどと読ませていただきました。

ところで。

> これらのデリゲートは表現力が弱い
僕は、“抽象度が高い=具体性に乏しい”ととらえています。

「なんでもかんでもはやめましょう」と主張されるのなら、じゃあどういうときはよくてどういうときはダメなのか、お伺いしたいです。

2009.05.24 02:30 URL | いげ太 #- [ 編集 ]


> 「なんでもかんでもはやめましょう」と主張されるのなら、じゃあどういうときはよくてどういうときはダメなのか、お伺いしたいです。

表現力が弱いという認識さえあれば、後は人それぞれの考え方で使い分けされれば良いと思ってます。
なのでその辺りには触れませんでしたが、僕としては「サンプルコードや使い捨てプログラムとかじゃない限りは基本的に使わない」ですかね。ただ、メソッドを非同期実行するためにデリゲートを使うときなんかは、パラメータの名称が付けられなくても問題ない場合もあるので、ケースバイケースかと思います。他には、クラスの内部でプライベートにしか使わない場合はもしかしたら使うかもしれません。

2009.05.24 11:15 URL | よこけん #Ay6tTHf6 [ 編集 ]


> 認識さえあれば、後は人それぞれ
ご利用は計画的に、ということでしょうか。

> 基本的に使わない
厳格なスタンスですね。僕とは真逆というか(^^;
開発の規模によって好ましいと思うスタンスが変わってくるのかもしれませんね。

2009.05.24 18:43 URL | いげ太 #- [ 編集 ]


古いエントリに失礼します。検索で見つけたので。
まったく同意します。
Dictionary 等にも同じ問題はありますね。内部処理ならともかく、インターフェイスとして IDictionary を使ったりすると。
しかし、C# 4.0 では Tuple が導入されるということで、ますますこの匿名化の傾向は加速する気がします。

個人的には、リネーム機構が欲しいです。
デリゲートならともかく、Tuple や Dictionary を避けて専用のクラスを作るのは大変なので、実装は流用しながら、パラメータの名前だけ変えられるといいなと思います。

2010.01.08 11:54 URL | aetos #- [ 編集 ]


あー Tuple もそうですねぇ。
個人的に、Tuple や Func デリゲートを、型パラメータの数が違うバージョンを一つずつ用意することで擬似的に可変長にしてるのも、好きになれないです。
まぁ擬似的だからと言って害があるわけではないので別にいいんですが。。。

> 個人的には、リネーム機構が欲しいです。

なるほど、それは良いですね。typedef みたいな感じですね。(typedef じゃ出来ませんが)

2010.01.09 03:04 URL | よこけん #Ay6tTHf6 [ 編集 ]












トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/252-bf856dbc