【问题标题】:List<Rectangle> - behaves like there is a boxingList<Rectangle> - 表现得像拳击
【发布时间】:2010-10-14 19:53:33
【问题描述】:

我们都知道泛型 List 不会装箱值类型。为什么在下面的代码 sn-p rects[1] 不受 Inflate 方法的影响?

如果没有装箱并且我想影响 rect[1],我需要编写三行代码,如图所示 - 已注释。有人可以解释一下吗?

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);
}

//Rectangle r = rects[1];
//r.Inflate(100, 100);
//rects[1] = r;

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

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

【问题讨论】:

  • 这是 C# 语言。

标签: c# list value-type


【解决方案1】:

这不是装箱 - 只是当您取出矩形时,您正在操作矩形的独立 副本

这是具有可变值类型(结构)的副作用之一。以及您不应该编写自己的可变结构的原因 - 太容易丢失数据。

由于您无法使预先构建的矩形不可变,恐怕您将不得不将其复制出来;变异它;然后放回去。

【讨论】:

  • 您能否解释一下堆栈和堆中元素的位置?我仍然无法理解它...
  • rects[1] 的值被复制到堆栈上。然后在这个 copy 上调用 Inflate 并且列表中的值不受影响。
  • 究竟什么时候使用copy?我的意思是:当我写 rect[1].Inflate 时,使用了 copy。那么,为什么当我写 rect[1] = new Rect(100,100) 时,新值会替换堆上的值而不是堆栈上的 copy 值?创建副本的规则是什么?
  • 更新现有结构值的唯一情况是使用字段局部变量或数组元素。在这种情况下,您正在调用 method([int] 索引器);这使用堆栈将矩形的新副本返回到本地堆栈(本质上是本地...
  • 变量)。因此,当您调用 rects[1].Inflate(...) 时,您正在改变堆栈上的值,然后丢弃它。
【解决方案2】:

因为Rectangle 是一个值类型,调用rects[1] 会在索引1 处复制Rectangle 实例。这正是值类型在.NET 中的工作方式,真的。

【讨论】:

    【解决方案3】:

    是的,如果您这样做,Rectangle 的值将被复制到您的本地变量中。

    这不叫拳击。这只是普通的复制,因为Rectangle 是一个值类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-07
      • 2010-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多