当前位置:  开发笔记 > 编程语言 > 正文

直接修改List <T>元素

如何解决《直接修改List<T>元素》经验,为你挑选了2个好方法。

我有这个结构:

struct Map
{
    public int Size;

    public Map ( int size )
    {
        this.Size = size;
    }

    public override string ToString ( )
    {
        return String.Format ( "Size: {0}", this.Size );
    }
}

使用数组时,它可以工作:

Map [ ] arr = new Map [ 4 ] {
    new Map(10),
    new Map(20),
    new Map(30),
    new Map(40)};

arr [ 2 ].Size = 0;

但是当使用List时,它不会编译:

List list = new List ( ) {
    new Map(10),
    new Map(20),
    new Map(30),
    new Map(40)};

list [ 2 ].Size = 0;

为什么?



1> Dirk Vollmar..:

C#编译器会给你以下错误:

无法修改'System.Collections.Generic.List.this [int]'的返回值,因为它不是变量

原因是结构是值类型,因此当您访问列表元素时,您实际上将访问由列表的索引器返回的元素的中间副本.

来自MSDN:

错误信息

无法修改'expression'的返回值,因为它不是变量

尝试修改作为中间表达式结果的值类型.由于该值未持久存在,因此该值将保持不变.

要解决此错误,请将表达式的结果存储在中间值中,或使用中间表达式的引用类型.

解决方案:

    使用数组.这使您可以直接访问元素(您不访问副本)

    当您创建Map类时,您仍然可以使用List来存储元素.然后,您将获得对Map对象的引用而不是中间副本,您将能够修改该对象.

    如果无法将Map从struct更改为类,则必须将列表项保存在临时变量中:

 

List list = new List() { 
    new Map(10), 
    new Map(20), 
    new Map(30), 
    new Map(40)
};

Map map = list[2];
map.Size = 42;
list[2] = map;


是的,http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldelema.aspx,但托管指针也可以从方法返回,C#不会这样做.

2> GvS..:

因为它是a struct,当使用List 时,你正在创建副本.

使用结构时,最好使它们不可变.这样可以避免这种效果.

使用数组时,您可以直接访问内存结构.使用List .get_Item处理返回值,即结构的副本.

如果它是一个类,你会得到一个指向该类的指针的副本,但你不会注意到这一点,因为指针隐藏在C#中.

同样使用List .ToArray也无法解决它,因为它将创建内部数组的副本,并返回此内容.

这不是你在使用结构时获得这样效果的唯一地方.

Divo提供的解决方案是一个非常好的解决方法.但是你必须记住以这种方式工作,不仅在使用List 时,而且在你想要更改结构内部的字段的任何地方.

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有