5

私はJonSkeetの書評を読んでいて、彼はHead First C#の多くの不正確さを調べています。

それらの1つが私の目を引きました:

[エラーセクションの下]構造体は常にスタック上に存在すると主張します。

どのような状況で構造体はスタックに存在しませんか?これは、私が構造体について知っていると思っていたものとは逆になります。

4

6 に答える 6

7

一般的な例の1つは、構造体がヒープに割り当てられたオブジェクトのメンバーである場合です。この質問には、さらに多くの詳細があります。.Netの構造体とクラスの違いは何ですか?

于 2009-02-10T08:51:37.543 に答える
4

それらがクラスのフィールドであるときはいつでも

これの珍しい例:

a:値型変数がキャプチャされた場合:

int i = 2;
Action action = delegate {i++;}
action();
Console.WriteLine(i);

これは、次のようにコンパイルされます。

class Foo {
    public int i;
    public void Bar() {i++;}
}
...
Foo foo = new Foo();
foo.i = 2;
Action action = foo.Bar;
action();
Console.WriteLine(foo.i);

b:値型変数がイテレータブロックで使用されている場合:

IEnumerable<int> GetValues() {
   for(int i = 0 ; i < 5 ; i++) yield return i;
}

(コンパイラーは、イテレーターを表すステートマシンを生成します。イテレーターのすべてのローカル変数(などi)はフィールドです)

于 2009-02-10T09:06:52.530 に答える
2

値型のインスタンスがボックス化されると、ボックス、つまりインスタンス自体がヒープに移動されます。ただし、最初に作成されたときの非クラスメンバー値型インスタンスが常にスタック上に作成されることは間違いありません。

構造体は値型です。したがって、上記のように動作します。

于 2009-02-10T08:52:46.773 に答える
2

1800情報からの答えの例として:

public class Foo
{
    int x;

    public Foo(int y)
    {
        x = y;
    }
}

...

Foo foo = new Foo(10);

これで、コンストラクターの実行が終了した後、の値foo.xは10foo.xになります。メモリーのどこにありますか?ヒープ上。の種類はfoo.x何ですか?int別名System.Int32、構造体です。

キャプチャされた変数やボクシングなどに関する他の回答も正しいですが(ボクシングの場合は「一種」-コメントを追加します)、この例は最も単純で最も重要なIMOです。

于 2009-02-10T09:07:35.867 に答える
0

この本は、タイピングの仕組みとスコープの仕組みを混同するという間違いを犯しました。値型は参照型ではありません。それを引数として使用してメソッドを呼び出すと、データがコピーされます(refまたはoutなし)。値型は、参照オブジェクトのようにヒープ上ではなく、メソッドのスコープ内のスタック上に存在しますが、常にスタック上に存在するわけではありません。

したがって、この本は、メカニズムの説明の代わりに使用方法の説明を作成しており、この 2 つを混同しています。まったく根拠のない主張ではありませんが、間違っています。

値型は、その所有者がどこにいても保持されます。

したがって、スコープがメソッドの場合、それらはスタック上にあります。それらのスコープがオブジェクトである場合、それらはヒープ上のオブジェクトと共に存続します。

したがって、ほとんどの人は値渡しの値型の仕組みを予測するのに苦労しているため、値型は不変のままにしておくのが最善であると言っても過言ではありません。

于 2012-01-26T20:38:10.823 に答える
0

すでに他の人によって詳細に言及されています

  • メンバー フィールドの値
  • ボックス化された構造体 (厳密には、値型ではなくなります)

加えて:

  • 構造体の配列は完全にヒープ上に存在します
  • 静的構造体 (スタックまたはヒープ上ではなく、独自の特別な領域内)
于 2009-02-10T12:11:15.650 に答える