5

我正在阅读 Jon Skeet 的书评,他正在研究Head First C#的许多不准确之处。

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

[在错误部分下] 声称结构始终存在于堆栈中。

在什么情况下结构不会存在于堆栈中?这与我认为我对结构的了解相反。

4

6 回答 6

7

一个常见的例子是结构是在堆中分配的对象的成员。这个问题在这里有很多额外的细节。.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 INFORMATION 的答案示例:

public class Foo
{
    int x;

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

...

Foo foo = new Foo(10);

现在,构造函数执行完毕后,值为foo.x10。foo.x内存在哪里?在堆上。是什么类型的foo.xintaka System.Int32,这是一个结构。

关于捕获的变量和装箱等的其他答案也是正确的(在装箱案例中“有点” - 我将添加评论),但这个例子是最简单和最重要的一个,IMO。

于 2009-02-10T09:07:35.867 回答
0

其他人已经深入提及

  • 成员字段值
  • 盒装结构(严格来说,它们不再是值类型)

此外:

  • 结构数组完全驻留在堆上
  • 静态结构(不在堆栈或堆上,而是在它们自己的特殊区域中)
于 2009-02-10T12:11:15.650 回答
0

这本书犯了将类型机制与作用域机制混淆的错误。值类型不是引用类型。当您调用使用它作为参数的方法时,它的数据被复制(没有 ref 或 out)。值类型将存在于方法范围内的堆栈中,而不是像引用对象那样存在于堆中,但这并不意味着它总是存在于堆栈中。

因此,这本书是在用一个用法说明来代替力学说明,并将两者混淆。这不是完全没有根据的说法,但这是错误的。

值类型将保存在其所有者所在的任何地方。

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

这样一来,可以很肯定地说,值类型最好保留为不可变的,因为大多数人很难预测按值的值类型机制。

于 2012-01-26T20:38:10.823 回答