[解決済み] なぜ構造体は継承をサポートしないのですか?
疑問点
.NETの構造体が継承をサポートしていないことは知っていますが、正確にはわかりません。 なぜ がこのように制限されている理由ははっきりしません。
構造体が他の構造体を継承できない技術的な理由は何ですか?
どのように解決するのですか?
値型が継承をサポートできないのは、配列のせいです。
問題は、パフォーマンスとGCの理由から、value型の配列は"inline"で保存されることです。 例えば、与えられた
new FooType[10] {...}
がある場合、もし
FooType
が参照型である場合、11個のオブジェクトが管理ヒープ上に作成されます(配列に1個、各型のインスタンスに10個)。 もし
FooType
が値型である場合、管理されたヒープ上に1つのインスタンスのみが作成されます -- 配列そのものに対してです (各配列値は配列と共に "inline"で保存されるからです)。
さて、値型による継承があったとします。 上記の配列の "インライン ストレージ" の動作と組み合わせると、次のように悪いことが起こります。 C++ では .
この擬似C#のコードを考えてみましょう。
struct Base
{
public int A;
}
struct Derived : Base
{
public int B;
}
void Square(Base[] values)
{
for (int i = 0; i < values.Length; ++i)
values [i].A *= 2;
}
Derived[] v = new Derived[2];
Square (v);
通常の変換ルールでは
Derived[]
への変換は
Base[]
(良くも悪くも)ですから、上の例でs/struct/class/gとすれば、何の問題もなく、期待通りにコンパイルされ実行されます。しかし、もし
Base
と
Derived
が値の型であり、配列がインラインで値を格納する場合、問題が発生します。
問題があるのは
Square()
について何も知らないからです。
Derived
について何も知らないので、配列の各要素にアクセスするためにポインタ演算だけを使い、 一定量ずつ増加する (
sizeof(A)
). アセンブリは漠然としたものになります。
for (int i = 0; i < values.Length; ++i)
{
A* value = (A*) (((char*) values) + i * sizeof(A));
value->A *= 2;
}
(そう、これは忌まわしいアセンブリですが、ポイントは、派生型が使用されているという知識なしに、既知のコンパイル時の定数で配列を通してインクリメントするということです)。
ですから、これが実際に起こった場合、メモリ破壊の問題が発生します。具体的には
Square()
,
values[1].A*=2
は
実際に
を変更することになります。
values[0].B
!
デバッグしてみる その !
関連
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み] AssemblyInfo.csは何に使うのですか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み] 私的相続、公的相続、保護相続の違いについて
-
[解決済み] C#で文字を繰り返し表示する最適な方法
-
[解決済み] Visual Studioのコンパイルエラー "mismatch between processor architecture "を修正するにはどうしたらいいですか?
-
[解決済み] ロックステートメントのボディ内で 'await' 演算子を使用できないのはなぜですか?
-
[解決済み】ExpandoObjectの本当のメリットは何ですか?
-
[解決済み] Java コンストラクタ継承
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] アセンブリから型を読み込めなかったエラー
-
[解決済み] VB.NETでプログラムパスを取得する?
-
[解決済み] Marginのプロパティ順
-
[解決済み] SQL Server Compact EditionデータベースのLINQ to SQLで、"Row not found or changed "例外を解決するにはどうすればよいですか?
-
[解決済み] ASP.NET control to render a <div>
-
[解決済み] LINQ to Entitiesはメソッドを認識しません。
-
[解決済み] .NETにおけるstructとclassの違いは何ですか?
-
[解決済み] 埋め込みリソーステキストファイルの読み方
-
[解決済み] .Any() vs .Count() > 0のどちらのメソッドがより良いパフォーマンスを発揮しますか?
-
[解決済み] LINQクエリでToList()とToArray()のどちらを呼び出すのが良いですか?