Delphiバリアントがオブジェクトを保持できないのはなぜですか?さらに重要なことに、この制限の背後にある理由は何ですか?
3 に答える
オブジェクトをVariant変数内に確実に格納できます。つまり、NativeUIntにキャストするだけです。とにかく、オブジェクトは単なるポインタです。
obj := TObject.Create;
v := NativeUInt(obj);
obj := TSomeObject(NativeUInt(v));
これは、バリアントが実行できることと実行できないことに関する私の経験からの単なる意見です。
COMオブジェクトを挿入すると、IDispatch参照として保存されるため、このオブジェクトでアクセスするメソッド呼び出しまたはプロパティは、メソッド/プロパティの内部DISPIDである配列を検索するコードに変換されます。メソッド引数を使用して構築され、メソッドはIDispatchインターフェイスを介して呼び出されます。
つまり、IDispatchは、通常の方法で処理されますが、コンパイラーによって自動的に実行されます。
ただし、通常のDelphiオブジェクトの場合、状況はさらに難しくなります。RTTIを使用して、公開されたメソッドとプロパティを検索して呼び出すことができますが、それだけです。公開されていない非仮想メソッドの名前がある場合、Delphiはメソッドでそのメソッドの正しいアドレスを見つけることができません。
言い換えれば、あなたができることは、オブジェクトを保持することだけであり、それを使用することはできません。おそらく彼らはそれを解放するためのサポートを追加することができますが、繰り返しますが、それはおそらくそれです。
IDispatchを正しく実装すれば、バリアントを介してオブジェクトを安全に保存および使用できることを私は知っています。これを実行するDelphiオブジェクトの基本クラスとして使用できるクラスがあります。公開されたメソッド/プロパティが自動的に公開され、必要に応じて、保護されたメソッド呼び出しを介してさらに追加できます。そのようなクラスに興味があれば、どこかに置くことができます。
ただし、これもIDispatchを介して行われ、公開されたメソッドを使用します。残りは手動コードであるため、バリアントのサポートをオブジェクトに組み込む必要があります。
それが彼らがちょうど言った理由だと思います:これはただオブジェクトを保持できるという不満を生み出すだけですが、それは役に立たないだけです。
しかし、それは私の考えです。おそらく誰かの役人がはるかに良い答えを持っています。
Variant の内部構造を使用して、過去に Variant を使用してオブジェクトを保持していました。コードは次のようになります。
var
MyObject: TMyObject;
Value: Variant;
begin
MyObject:= TMyObject.Create;
TVarData(Value).VType:= VarByRef or VarUnknown;
TVarData(Value).VPointer:= MyObject;