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ブロックを使用して、必要に応じて「デフォルトクラス」プロパティを一時的に置き換え、復元します。クラス参照変数を使用してこれを行うのははるかに簡単であり、代わりにジェネリックを使用して行うことはできません。
TClass
サンプルコードを使用して、a が役立つ1つまたは2つの具体例を提供できますか?についてのインターネットでの大まかなTClass
調査でTClass
は、パラメータとして渡すことができることがわかりました。これは、Genericsを使用して.NETで行われます。ファクトリメソッドはstatic
、.NETで単にマークされ、実行するためにクラスインスタンスを必要としません。
TClass
コンパイラのサポートを必要とする基本的な言語機能です。独自の言語を作成せずに「独自に作成」することはできません。.NETの場合でも、オブジェクトモデルは個々の言語ではなくCLRによって定義されるため、それでも十分ではありません。これは、文字通り.NETフレームワーク自体の一部である必要があるか、存在しないものです。