callvirt
基本的な理由/問題は、CLS 仕様 (言語が .net と対話する方法を定義する) の設計者が、クラス メンバーが を介してではなく直接呼び出す必要があることを指定できる手段を定義しなかったことです。 null 参照チェック; また、「通常の」ボクシングの対象とならない構造を定義する手段も提供しませんでした。
CLS 仕様でこのような手段が定義されていれば、.net は共通オブジェクト モデル (COM) によって確立されたリードに一貫して従うことができます。COM では、null 文字列参照は意味的に空の文字列と同等と見なされていました。同様にデフォルト値を定義するための値セマンティクスを持つと想定されるユーザー定義の不変クラス型。本質的には、 の各メンバーに対してString
、たとえばのLength
ように記述されます[InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }
。このアプローチは、値のように動作する必要があるものに対して非常に優れたセマンティクスを提供しますが、実装の問題により、ヒープに格納する必要があります。このアプローチの最大の問題は、そのような型との間の変換のセマンティクスがObject
少し曖昧になる可能性があることです。
別のアプローチは、継承ではなくObject
、代わりにカスタムのボックス化およびボックス化解除操作 (他のクラス型との間で変換される) を持つ特別な構造型の定義を許可することでした。このようなアプローチでは、 string と同じように動作する class typeと、 typeの単一のプライベート フィールドを保持するNullableString
カスタム ボックス化された struct typeが存在します。をorに変換しようとすると、null 以外の場合、または null の場合に返されます。にキャストしようとすると、インスタンスへの null 以外の参照が参照を格納します (長さがゼロの場合は null を格納する可能性があります)。他の参照をキャストすると、例外がスローされます。String
Value
String
String
NullableString
Object
Value
String.Empty
String
NullableString
Value
文字列はヒープに格納する必要がありますが、概念的には、null 以外の既定値を持つ値型のように動作してはならない理由はありません。それらを参照を保持する「通常の」構造として格納することは、それらを「文字列」型として使用するコードにとっては効率的でしたが、「オブジェクト」にキャストするときに間接的で非効率的なレイヤーが追加されました。現時点で上記の機能のいずれかが .net に追加されるとは考えていませんが、将来のフレームワークの設計者はそれらを含めることを検討する可能性があります。