なぜ.NETフレームワークには、ファーストクラス型としてのクラスの概念がないのですか?
C#と.NETフレームワークは、Delphiの主任開発者であるAnders Hejlsbergによって設計された、本質的に「Javaのように書き換えられたDelphi」として始まったという歴史に詳しい人にはよく知られています。それ以来、物事はかなり分かれていますが、類似点の初期には非常に明白だったため、。 しかし、私は最近いくつかの.NETのものを見てきましたが、Delphiの最も興味深く有用な機能の1つは完全に欠落しているようです。それに慣れていない人のTClassために、Type型は.NET の型と同様に、クラスへの参照を表します。しかし、.NETがTypeリフレクションに使用する場合、DelphiはTClass言語の非常に重要な組み込み部分として使用します。クラスサブタイプ変数や仮想クラスメソッドなど、それなしでは存在しない、存在できないさまざまな便利なイディオムが可能になります。 すべてのOO言語には仮想メソッドがあり、異なるクラスがメソッドの同じ基本概念を異なる方法で実装し、その後、呼び出されたオブジェクトインスタンスの実際のタイプに基づいて実行時に適切なメソッドが呼び出されます。Delphiは、この概念をクラスに拡張します。特定のクラスサブタイプとして定義されたTClass参照がある場合(つまりclass of TMyClass、変数が継承する任意のクラス参照を受け入れることができますがTMyClass、階層スコープの外部ではない)それは、クラスの実際の型を使用して、インスタンスなしで呼び出すことができます。たとえば、このパターンをコンストラクターに適用すると、Factory実装が簡単になります。 .NETには同等のものはないようです。クラス参照(特に仮想コンストラクタや他の仮想クラスメソッド!)と同じくらい便利なのに、なぜそれらが取り残されたのかについて何か言いましたか? 具体例 フォームの逆シリアル化 Delphi VCLはDFM、コンポーネント階層を記述するためのDSL である形式でフォームを保存します。フォームリーダーがDFMデータを解析すると、次のように記述されているオブジェクト間で実行されます。 object Name: ClassName property = value property = value ... object SubObjectName: ClassName ... end end ここで興味深いのはそのClassName部分です。各コンポーネントクラスは、その時点でTClassコンポーネントストリーミングシステムに登録しinitializationます(静的コンストラクターは、わずかに異なるだけで、起動時に直ちに発生することが保証されています)。これにより、クラス名をキーとしてstring-> TClassハッシュマップに各クラスが登録されます。 各コンポーネントはから派生しTComponent、単一の引数をとる仮想コンストラクタを持ちますOwner: TComponent。どのコンポーネントもこのコンストラクタをオーバーライドして、独自の初期化を提供できます。DFMリーダーはクラス名を読み取ると、前述のハッシュマップで名前を検索し、対応するクラス参照を取得し(または、存在しない場合は例外を発生させます)、仮想TComponentコンストラクターを呼び出します。これは、登録関数がTComponentから派生するために必要なクラス参照を取得し、適切なタイプのオブジェクトが作成されるためです。 これがないと、WinFormsの同等物は...まあ...それを率直に言って大きな混乱であり、新しい.NET言語が独自のフォーム(デ)シリアル化を完全に再実装する必要があります。考えてみると、これは少し衝撃的です。CLRを持つことの全体的な目的は、複数の言語で同じ基本インフラストラクチャを使用できるようにすることなので、DFMスタイルのシステムは完全に理にかなっているでしょう。 拡張性 私が書いたイメージマネージャークラスには、データソース(イメージファイルへのパスなど)を提供し、コレクションにはないがデータソースでは使用可能な名前を取得しようとすると、新しいイメージオブジェクトを自動的に読み込みます。class ofベースイメージクラスとして型付けされたクラス変数があり、作成される新しいオブジェクトのクラスを表します。デフォルトが付属していますが、特別な目的で新しい画像を作成する場合、画像をさまざまな方法で設定する必要があるという点がいくつかあります。(アルファチャネルなしで作成する、PNGファイルから特殊なメタデータを取得してスプライトサイズを指定するなど) これは、大量の構成コードを記述し、新しいオブジェクトを作成する可能性のあるすべてのメソッドに特別なオプションを渡すことで実行できます...または、仮想メソッドをオーバーライドするベースイメージクラスのサブクラスを作成することもできます。問題のアスペクトが構成された後、try / finallyブロックを使用して、必要に応じて「デフォルトクラス」プロパティを一時的に置き換え、復元します。クラス参照変数を使用してこれを行うのははるかに簡単であり、代わりにジェネリックを使用して行うことはできません。