C#Indexer内存问题

时间:2009-03-22 14:38:44

标签: c# stack heap indexer

我在main方法中有以下代码:

List<Rectangle> rects = new List<Rectangle>();

for (int i = 0; i < 5; i++)
{
    rects.Add(new Rectangle(1, 1, 1, 1));
}

foreach (Rectangle item in rects)
{
    Console.WriteLine(item);
}

rects[1].Inflate(100, 100);

foreach (Rectangle item in rects)
{
    Console.WriteLine(item);
}

在提供的代码中,[1]保持不变。这是因为索引器(仍然是一种特殊方法)返回了矩形结构的副本。在这种情况下,元素位于上。索引器通过将新的 copy 放在堆栈上来返回元素的新副本(因为Rectangle是值类型)。

到目前为止一直很好......

后来我在Program类中创建了一个Rectangle结构数组:

 Rectangle[] rect = new Rectangle[] { new Rectangle(1, 1, 1, 1), new Rectangle(1, 1, 1, 1) };

主要方法:

Program p = new Program();

p.rect[1].Inflate(100, 100);

foreach (var item in p.rect)
{
    Console.WriteLine(item);
}

我预计rect数组的索引器也会返回矩形结构的 copy ,但这次原始元素(也位于上)已被更改

为什么?数组索引器是否以不同的方式工作?

亲切的问候 PK

4 个答案:

答案 0 :(得分:3)

由此可以得出结论,列表上的索引器是一个方法调用,它在从方法返回时将值类型的值放在堆栈上,并且数组索引器实际上是在代码中转换为计算偏移量的数组的开头是一个直接的内存引用。

答案 1 :(得分:0)

是。数组索引器表示要直接更改的变量。索引器基本上是一个带有索引参数的方法,其中应用了语法糖。

同样的差异适用于字段和属性。

如果你从索引器返回一个引用类型,它就没那么大的区别,因为它会引用同一个对象。但是当你返回一个struct实例(或任何值类型)时,返回时会复制该值并且你试图修改副本,这几乎没用。

答案 2 :(得分:0)

据我所知,数组的“索引器”实际上并不是索引器。由于其特殊的作用,数组(或更确切地说是数组类型)不能被视为.NET Framework中的普通类型。 (举另一个例子,数组项是协变的,这在许多情况下有助于导致异常与其他类型相比)。它只是引用数组的第n个元素,因此它返回的对象实际上是存储在数组中的实际对象。只是分开处理这两个概念。它们具有相同语法的事实在这里并不重要 - 功能上有一些相似之处,但并不多。

答案 3 :(得分:0)

如前所述,数组是CLI中的特殊内容。他们没有索引器。 “索引”到数组中直接转换为适当的ldelem CIL指令。