1. ホーム
  2. c#

[解決済み] ValueTypesはどのようにObject(ReferenceType)から派生し、なおかつValueTypesであるのか?

2023-03-26 12:13:16

質問

C#は構造体をクラスから派生させることはできませんが、すべてのValueTypesはObjectから派生します。この区別はどこにあるのでしょうか?

CLRはこれをどのように処理するのでしょうか?

どのように解決するのか?

C#は構造体をクラスから派生させることができない

あなたの発言は不正確です。したがって、あなたは混乱しています。C# は構造体をクラスから派生させることができます。すべての構造体は、System.Objectから派生した同じクラスであるSystem.ValueTypeから派生しています。そして、すべての列挙型は System.Enum から派生します。

UPDATE: いくつかのコメント (現在は削除されています) で、明確化を必要とするいくつかの混乱がありました。私はいくつかの追加の質問をします。

構造体は基本型から派生するのですか?

明らかにイエスです。これは仕様書の最初のページを読めばわかります。

intやdoubleなどのプリミティブ型を含むすべてのC#の型は、1つのルートオブジェクト型から継承されます。

さて、ここで仕様が誇張していることに気づきます。ポインター型はオブジェクトから派生しませんし、インターフェイス型や型パラメーター型の派生関係は、このスケッチが示すよりも複雑です。しかし、すべての構造体型が基本型から派生することは明らかです。

struct 型が基底型から派生していることを知るための他の方法はありますか?

もちろん、構造体型は ToString . もしベース型の仮想メソッドでなければ、何をオーバーライドしているのでしょうか? したがって、構造体には基底型が必要です。その基底型はクラスです。

ユーザ定義構造体を任意のクラスから派生させてもよいですか?

明らかにノーです。 これは、構造体がクラスから派生しないことを意味するものではありません。 . 構造体はクラスから派生し、それによってそのクラスの継承可能なメンバを引き継ぎます。 実際、構造体は 必須 であり、特定のクラスから派生する必要があります。列挙型は Enum 構造体は ValueType . これらは 必須 であるため,C#言語では は禁じています。 を禁止しています。

なぜ禁止するのですか?

関係がある場合 必須 である場合、言語設計者にはオプションがあります。(1)ユーザーに必須の呪文を入力させる、(2)任意にする、(3)禁止する。それぞれに長所と短所があり、C# 言語設計者はそれぞれの具体的な内容に応じて異なる選択をしています。

例えば、constフィールドは静的であることが要求されますが、そうすることは第一に無意味な文言であり、第二に静的でないconstフィールドが存在することを意味するため、そうすることは禁止されています。しかし、オーバーロードされた演算子は、開発者に選択の余地がないにもかかわらず、staticとマークすることが要求されます。そうしないと、開発者は演算子のオーバーロードがインスタンスメソッドであると簡単に信じてしまいます。これは、ユーザーが "static" が、たとえば "virtual" も可能であることを意味すると信じるようになるかもしれないという懸念より優先されます。

この場合、構造体が ValueType から派生していると言うことをユーザーに要求することは、単なる過剰な説明のように思われ、それは構造体の を意味します。これらの問題を解消するために、C#では 違法 構造体が基底型から派生していることは明らかですが、コード内でそれを記述することは違法です。

同様に、すべてのデリゲート型は MulticastDelegate を継承しますが,C#では ではなく と言う必要があります。

さて、これで確立したのは C#のすべての構造体はクラスから派生しています。 .

とはどのような関係なのでしょうか? 継承 クラスからの派生 ?

多くの人がC#の継承関係で混乱しています。構造体、クラス、デリゲート型Dがクラス型Bから派生した場合、Bの継承可能なメンバはDのメンバでもある、というように非常に単純な継承関係です。

ValueTypeから構造体を派生させるというのは、継承に関してどのような意味があるのでしょうか。 単純に、ValueType の継承可能なメンバはすべて構造体のメンバでもあるということです。このようにして、構造体は ToString の実装は、構造体のベース クラスから継承されます。

すべての継承可能なメンバ?もちろん違います。プライベートメンバーは遺伝するのでしょうか?

はい、そうです。ベースクラスのすべてのプライベートメンバは、派生クラスのメンバでもあります。もちろん、これらのメンバを名前で呼び出すことは違法ですが、呼び出し先が アクセシビリティドメイン にない場合は、もちろん違法です。メンバーを持っているからと言って、使っていいわけではないのです

では、本来の答えを続けます。


CLRはどのようにこれを処理するのでしょうか?

極めて良好です :-)

値型を値型たらしめているのは、そのインスタンスが 値によってコピーされる . 参照型を参照型たらしめているのは、そのインスタンスが によってコピーされることです。 . という信念があるようですが 継承 の関係が特別で珍しいという信念があるようですが、その信念が何であるのか理解できません。 継承は物事のコピーの仕方とは関係ない。

こう考えてみてください。 次のような事実を話したとします。

  • 箱には、赤い箱と青い箱の2種類があります。 と青い箱の2種類があります。

  • 赤い箱はすべて空です。

  • O、V、Eと呼ばれる3つの特別な青い箱があります。

  • Oはどの箱の中にも入っていません。

  • VはOの中にある。

  • EはVの内部にある。

  • Vの中に他の青い箱はない。

  • Eの中に青い箱はありません。

  • すべての赤い箱はVかEの中にある。

  • O以外のすべての青色ボックスは、それ自身が青色ボックスの中にある。

青枠は参照型、赤枠は値型、O は System.Object, V は System.ValueType, E は System.Enum で、 "inside" の関係は "derives from" となっています。

これは完全に一貫したわかりやすいルールで、たくさんの厚紙とたくさんの忍耐力があれば、簡単に自分で実装することができます。箱が赤か青かは、中に何が入っているかとは関係ありません。現実の世界では、青い箱の中に赤い箱を入れることは完全に可能です。CLR では、参照型を継承する値型を作ることは、それが System.ValueType か System.Enum のいずれかである限り、完全に合法です。

では、質問を言い換えてみましょう。

ValueTypesはどのようにObject(ReferenceType)から派生し、なおかつValueTypesであるのでしょうか?

として

<ブロッククオート

すべての赤い箱(値型)が青い箱(参照型)である箱O(System.Object)の内部にあり(派生し)、なおかつ赤い箱(値型)であることは、どのようにして可能なのでしょうか?

そういう言い方をすると、当たり前なんだけどね。青であるボックス O の中にあるボックス V の中に赤いボックスを置くことを止めるものは何もありません。なぜそうなるのでしょうか?


追加の更新です。

Joan の最初の質問は、それがどのようなものであるかということでした。 可能である が可能であるかということです。つまり、参照先のデータがオブジェクト ヘッダーを持つかどうか、同期ブロックを持つかどうか、ガベージ コレクションのために独自のストレージを所有するかどうか、などです。これらのメカニズムは複雑で、1回の回答では説明しきれないほどです。CLRの型システムのルールは、C#で見られるようなやや単純化された味付けよりもかなり複雑で、たとえば型のボックス化バージョンと非ボックス化バージョンの間に強い区別があるわけでもない。また、ジェネリックの導入により、CLRに複雑さが大幅に追加された。ボックス化および制約付き仮想呼び出しのルールに特に注意して、詳細についてはCLI 仕様を参照してください。