我正在阅读Jon Skeet的书评,他正在查看numerous inaccuracies的Head First C#。
其中一个引起了我的注意:
[在Errors Section下]声称结构总是存在于堆栈中。
在什么情况下,不会在堆栈中生效?这与我认为的结构相反。
答案 0 :(得分:7)
一个常见示例是struct是堆中分配的对象的成员。这里有很多额外的细节问题。 What’s the difference between struct and class in .Net?
答案 1 :(得分: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
)都是字段)
答案 2 :(得分:2)
当value type的实例获得boxed时,该框以及实例本身将被移动到堆中。尽管如此,毫无疑问,首次创建的非类成员值类型实例总是在堆栈上创建。
结构是一种值类型。所以它的行为如上所述。
答案 3 :(得分:2)
仅作为the answer from 1800 INFORMATION的一个例子:
public class Foo
{
int x;
public Foo(int y)
{
x = y;
}
}
...
Foo foo = new Foo(10);
现在,在构造函数完成执行后,foo.x
的值为10.内存中的foo.x
在哪里?在堆上。 foo.x
的类型是什么? int
又名System.Int32
,这是一个结构。
关于捕获的变量和拳击等的其他答案也是正确的(拳击案例中的“排序” - 我将添加评论),但这个例子是最简单和最重要的一个,IMO。
答案 4 :(得分:0)
其他人已经深入提及
另外:
答案 5 :(得分:0)
这本书错误地将打字机制与范围机制混为一谈。 值类型不是引用类型。当您使用它作为参数(没有ref或out)调用方法时,会复制数据。 值类型将作为方法范围存在于堆栈中,而不是作为引用对象存在于堆上,但这并不意味着它将始终存在于堆栈中。
所以,这本书正在用一个用法语句来代替一个机制陈述,并使两者混淆。这不是一个毫无根据的说法,但这是错误的。
价值类型将在其所有者所在的任何地方举行。
因此,如果他们的范围是一个方法,他们将在堆栈中。如果它们的作用域是一个对象,它们将与堆上的对象一起使用。
有了它,可以肯定地说,值类型最好留作不可变的,因为大多数人很难预测按值的值类型机制。