【问题标题】:C# Value Type ListsC# 值类型列表
【发布时间】:2016-01-02 20:16:05
【问题描述】:

我有点困惑。结构或多或少是在堆栈上构造的值类型,因此具有简单的生命周期。

使用结构体构建列表时,不能直接修改,因为返回值是一个副本,实际上不会修改列表中存储的项目。

我的困惑来了:为什么我不能直接更改列表中的结构项,但我可以直接访问和修改基值类型(int、float 等...)?

这行得通:

 List<int> foobar1 = new List<int>();
 foobar1.Add(1);
 foobar1[0] = 2;

这不是:

public struct foo
{
    public int bar;
}

...         

List<foo> foobar2 = new List<foo>();
foobar2.Add(new foo());
foobar2[0].bar = 2;

【问题讨论】:

    标签: c# list collections value-type


    【解决方案1】:

    两者本质上是不同的,不仅仅是因为有人认为它是,让我解释一下。

    第一段代码替换列表中第 0 个元素位置的 int 值。存在哪个int 值并不重要,之后列表会在第0 位包含int2

    然而,第二段代码试图替换结构的部分。是的,我知道,结构只有一个字段,但编译器没有这样的区别。您正在有效地修改从列表中检索到的结构的副本。这是不允许的。

    所以第一段代码只是将一个新的值类型塞入列表中,第二段代码尝试从列表中修改值类型,这是一个副本。

    那么,您能否将第二段代码更改为与第一段相同,即。完全替换列表中的元素?

    当然:

    var temp = foobar[0];
    temp.bar = 2;
    foobar2[0] = temp; // no longer modifies the copy, but replaces the element
    

    基本上就在这里:

    foobar2[0].bar = 2;
              ^    ^
              |    |
    

    是问题所在。

    【讨论】:

    • 更有意义,所以如果我要修改我必须用一个全新的 foo 替换它
    • 您可以读取副本,在本地修改副本(在局部变量中),然后将修改后的副本填回到列表中,只是不允许在一个语句中完成所有这些操作。
    • 好吧。 foobar[0] = new foo { bar = foobar[0].bar + 2 }; 但这太丑了。
    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 2010-12-06
    相关资源
    最近更新 更多