私はJonSkeetの書評を読んでいて、彼はHead First C#の多くの不正確さを調べています。
それらの1つが私の目を引きました:
[エラーセクションの下]構造体は常にスタック上に存在すると主張します。
どのような状況で構造体はスタックに存在しませんか?これは、私が構造体について知っていると思っていたものとは逆になります。
私はJonSkeetの書評を読んでいて、彼はHead First C#の多くの不正確さを調べています。
それらの1つが私の目を引きました:
[エラーセクションの下]構造体は常にスタック上に存在すると主張します。
どのような状況で構造体はスタックに存在しませんか?これは、私が構造体について知っていると思っていたものとは逆になります。
一般的な例の1つは、構造体がヒープに割り当てられたオブジェクトのメンバーである場合です。この質問には、さらに多くの詳細があります。.Netの構造体とクラスの違いは何ですか?
それらがクラスのフィールドであるときはいつでも
これの珍しい例:
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
)はフィールドです)
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です。
この本は、タイピングの仕組みとスコープの仕組みを混同するという間違いを犯しました。値型は参照型ではありません。それを引数として使用してメソッドを呼び出すと、データがコピーされます(refまたはoutなし)。値型は、参照オブジェクトのようにヒープ上ではなく、メソッドのスコープ内のスタック上に存在しますが、常にスタック上に存在するわけではありません。
したがって、この本は、メカニズムの説明の代わりに使用方法の説明を作成しており、この 2 つを混同しています。まったく根拠のない主張ではありませんが、間違っています。
値型は、その所有者がどこにいても保持されます。
したがって、スコープがメソッドの場合、それらはスタック上にあります。それらのスコープがオブジェクトである場合、それらはヒープ上のオブジェクトと共に存続します。
したがって、ほとんどの人は値渡しの値型の仕組みを予測するのに苦労しているため、値型は不変のままにしておくのが最善であると言っても過言ではありません。
すでに他の人によって詳細に言及されています
加えて: