なぜ.NETフレームワークには、ファーストクラス型としてのクラスの概念がないのですか?


20

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ブロックを使用して、必要に応じて「デフォルトクラス」プロパティを一時的に置き換え、復元します。クラス参照変数を使用してこれを行うのははるかに簡単であり、代わりにジェネリックを使用して行うことはできません。



3
TClassサンプルコードを使用して、a が役立つ1つまたは2つの具体例を提供できますか?についてのインターネットでの大まかなTClass調査でTClassは、パラメータとして渡すことができることがわかりました。これは、Genericsを使用して.NETで行われます。ファクトリメソッドはstatic、.NETで単にマークされ、実行するためにクラスインスタンスを必要としません。
ロバートハーヴェイ14

7
@RobertHarvey:個人的には、Java / C ++がリロードされ、オブジェクトを含むModula-2として扱われるようになったので、C#を見るのをやめると、C#の意味が大きくなり始めました。Javaでも同じです。誰もがC ++の影響を受けたと言いますが、そうではありません。その主な影響はObjective-C(およびそれを介したSmalltalk)であり、GCを使用したC ++ではなく型を使用したSmalltalkとして扱うと、Javaの意味が大きくなります。
ヨルグWミットタグ14

3
@RobertHarvey:TClassコンパイラのサポートを必要とする基本的な言語機能です。独自の言語を作成せずに「独自に作成」することはできません。.NETの場合でも、オブジェクトモデルは個々の言語ではなくCLRによって定義されるため、それでも十分ではありません。これは、文字通り.NETフレームワーク自体の一部である必要があるか、存在しないものです。
メイソンウィーラー14

4
まず第一に、.NETはもともと「Borland」の製品ではなかったと、私は最大限に確信をもって言うことができます。これをどうやって知るのですか?私は(まだ)Delphiを開発した元のコアチームの一員でした。私はアンダース、チャック、ゲイリーなどと密接に仕事をしました。もちろん、あなたはこれを知っていると確信しています。.NETでのクラス参照の存在(TClassおよび同様の構造が呼び出される)については、実行時のアクセス可能な型情報が豊富に存在するため、不要であると考えられていました。Delphiの最初の型情報ははるかに少なく、クラス参照は妥協でした。
アレンバウアー

回答:


5

.NET(CLR)はMicrosoftの第3世代のコンポーネントオブジェクトモデル(COM)であり、初期の頃は "COM +ランタイム"と呼ばれていました。Microsoft Visual BasicおよびCOM / ActiveXコントロール市場は、Borland Delphiよりも特定のCLRアーキテクチャの互換性の選択により大きな影響を与えています。(確かに、DelphiがActiveXコントロールを採用したという事実は、ActiveXエコシステムの成長に確実に役立ちましたが、COM / ActiveXはDelphiより前に存在していました)

COMのアーキテクチャはC(C ++ではなく)で作成され、クラスではなくインターフェイスに焦点を合わせました。さらに、オブジェクト構成をサポートしました。つまり、COMオブジェクトは、実際には複数の異なるオブジェクトで構成され、IUnknownインターフェイスがそれらをリンクします。ただし、IUnknownにはCOMオブジェクトの作成に役割がありません。これは、可能な限り言語に依存しないように設計されています。オブジェクトの作成は通常IClassFactoryによって処理され、ITypeLibraryおよび関連するインターフェイスによって反映されました。この懸念の分離は実装言語に依存せず、各コアCOMインターフェイスの機能は最小限で直交していました。

そのため、COMおよびActiveXコントロールの人気の結果、.NETアーキテクチャはCOM IUnknown、IClassFactory、およびITypeLibraryをサポートするように構築されました。COMでは、これらのインターフェイスは必ずしも同じオブジェクト上にあるとは限らなかったため、これらをまとめてまとめても必ずしも意味がありませんでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.