什么时候结构不在堆栈上?

时间:2009-02-10 08:48:28

标签: c# stack struct

我正在阅读Jon Skeet的书评,他正在查看numerous inaccuraciesHead First C#

其中一个引起了我的注意:

  

[在Errors Section下]声称结构总是存在于堆栈中。

在什么情况下,会在堆栈中生效?这与我认为的结构相反。

6 个答案:

答案 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)调用方法时,会复制数据。 值类型将作为方法范围存在于堆栈中,而不是作为引用对象存在于堆上,但这并不意味着它将始终存在于堆栈中。

所以,这本书正在用一个用法语句来代替一个机制陈述,并使两者混淆。这不是一个毫无根据的说法,但这是错误的。

价值类型将在其所有者所在的任何地方举行。

因此,如果他们的范围是一个方法,他们将在堆栈中。如果它们的作用域是一个对象,它们将与堆上的对象一起使用。

有了它,可以肯定地说,值类型最好留作不可变的,因为大多数人很难预测按值的值类型机制。