8

クラスの値型プロパティに関して、スタックとヒープで何が起こっているのか混乱しています。

これまでの私の理解:

次のような構造体 (値型) を持つクラスを作成すると、次のようになります。

class Foo
{
  private Bar _BarStruct;
  public Bar BarStruct
  {
    get {return _BarStruct; }
    set {_BarStruct = value; }
   }
}

private struct Bar
{
  public int Number;
  Bar()
  {
    Number = 1;
  }
  Bar(int i)
  {
    Number = i;
  }
}

次のようにクラス インスタンスを作成する場合:

Foo fooObj = new Foo();

スタックとヒープは次のようになります。

https://i962.photobucket.com/albums/ae105/acardy/stackheap-1.jpg(https://i962.photobucket.com/albums/ae105/acardy/stackheap-1.jpg)

...Bar 構造体がヒープ内の Foo クラスに埋め込まれている場所。これは私には理にかなっていますが、Foo オブジェクト内で BarStruct クラスの Number 整数を変更することを検討すると、それが失われ始めます。例えば:

Foo fooObj = new Foo();
fooObj.BarStruct.Number = 1;

私が理解しているように、これは BarStruct のコピーを返してスタック上に置く必要があります。つまり、BarStruct のメンバーの変更はオブジェクトに反映されないため、上記の最後の行でエラーが発生します。

ここまででいいの?

もしそうなら、私の質問は、どうしてこのような割り当てが来るのかということです:

fooObj.BarStruct = new Bar(2);

...有効で、ヒープ値を変更しますか? 確かに、これはスタック上の値を変更しているだけですか?? また、(次第に)値型で new を使用できるのは非常に紛らわしいと思います。私にとって、new は (C++ のように) ヒープに割り当てるためのものであり、スタック上のアイテムに対してこれを行うのは不自然に感じます。

質問を繰り返しますが、構造体を含むプロパティが呼び出されたときに何が起こるか、新しい構造体をコピーに割り当てることができるのに、ヒープの参照が変更されるのはなぜですか?

これがすべて理にかなっていることを本当に願っています。

説明が必要な場合は叫んでください!

タ、

アンディ。

4

1 に答える 1

10

この割り当てを見て:

fooObj.BarStruct = new Bar(2);

割り当てはスタックの値を変更していません-プロパティのセッターを呼び出しています。

つまり、最初の割り当ては次のようになります。

fooObj.get_BarStruct().Number = 1; // Bad

2 番目は次と同等です。

fooObj.set_BarStruct(new Bar(2));

それは役に立ちますか?

最初から値の型を不変にすると、問題のある代入は問題にならなくなることに注意してください。実際、これは一般的に役立ちます。可変値型は、C# では非常に悪い考えです。あなたは彼らと終わりのないトラブルに巻き込まれることができます.

「新しい」というあなたの期待に関しては、基本的にC++で考えないようにしてください。C# は C++ ではなく、C# で効果的に C++ を記述しようとすると、さまざまな要素 (デストラクタ、ジェネリック、構築中の動作) が混乱を招きます。"new" ステートメントは、値型か参照型かにかかわらず、型の新しいインスタンスを作成します。

于 2010-01-04T13:28:39.103 に答える