web-dev-qa-db-ja.com

C#ではジェネリック型として 'void'を使用できないのはなぜですか

voidが構築可能でなく、ジェネリック型として許可されないことを支持して主張した設計上の決定は何でしたか?結局のところ、それは特別な空のstructであり、別個のFuncActionデリゲートを持つことによるPITA全体を回避することになります。

(C++ではvoidを明示的に返し、テンプレートパラメータとしてvoidを許可します)

53
user23157

「void」の根本的な問題は、それが他の戻り型と同じことを意味しないことです。 「void」は、「このメソッドが返す場合、値をまったく返さない」ことを意味します。 nullではありません。 nullは値です。値はまったく返されません。

これは本当に型システムを台無しにしてしまいます。型システムは基本的に、特定の値に対して有効な操作について論理的な推論を行うためのシステムです。 voidを返すメソッドは値を返さないため、「この操作で有効な操作は何か」という質問です。まったく意味がありません。有効または無効な操作があるための「もの」はありません。

さらに、これはランタイムを混乱させるものです。 .NETランタイムは、スタックマシンとして指定されている仮想実行システムの実装です。つまり、評価スタックへの影響に関して操作がすべて特徴付けられている仮想マシン。 (もちろん、実際にはマシンはスタックとレジスタの両方を備えたマシンに実装されますが、仮想実行システムはスタックのみを想定しています。)voidメソッドの呼び出しの効果はfundamentallyvoid以外のメソッドの呼び出しの効果とは異なります。 void以外のメソッドは常にスタックに何かを置きます。 voidメソッドがスタックに何かを置くことはありません。したがって、メソッドの戻り値が無視された場合、コンパイラーはvoidメソッドと非voidメソッドを同じに処理できません。メソッドがvoidの場合、戻り値がないため、ポップは発生しません。

これらすべての理由により、「void」はインスタンス化できるタイプではありません。 値がありません、それがポイントです。オブジェクトに変換することはできません。また、voidを返すメソッドは、voidを返さないメソッドでポリモーフィックに処理することはできません。

したがって、あなたが注意しているように、voidは残念ながら型引数として使用できません。とても便利でしょう。

後知恵の恩恵により、何もせずに、voidを返すメソッドが自動的に魔法のシングルトン参照型である「Unit」を返すと、関係者全員にとってより良かったでしょう。 すべてのメソッド呼び出しがスタックに何かを置くことを知っているでしょうすべてのメソッド呼び出しが変数の変数に割り当てることができる何かを返すことを知っているでしょうオブジェクトタイプ、そしてもちろんUnitはタイプ引数として使用できるため、個別のActionとFuncデリゲートタイプを持つ必要はありません。悲しいことに、それは私たちがいる世界ではありません。

この静脈のいくつかのより多くの考えについては以下をご覧ください:

69
Eric Lippert

差出人: http://connect.Microsoft.com/VisualStudio/feedback/details/94226/allow-void-to-be-parameter-of-generic-class-if-not-in-c-then-ジャストインランタイム

これは実際には仕様によるものです-void型のインスタンスは(ランタイムの他の多くの型とともに)許可されません。 voidまたはvoid []もCreateInstanceできません。セキュリティのためにこれらのタイプの穴を塞いだ。

私の人生では、セキュリティホールがいかに空虚であるかを知ることはできません。

9
Winston Ewert