更改结构列表中元素的值

时间:2020-03-05 18:49:56  来源:igfitidea点击:

我有一个结构列表,我想更改一个元素。例如 :

MyList.Add(new MyStruct("john");
MyList.Add(new MyStruct("peter");

现在,我想更改一个元素:

MyList[1].Name = "bob"

但是,每当我尝试执行此操作时,都会出现以下错误:

Cannot modify the return value of
  System.Collections.Generic.List.this[int]‘ because it is not
  a variable

如果我使用类列表,则不会发生此问题。

我猜答案与结构是值类型有关。

因此,如果我有一个结构体列表,是否应该将它们视为只读结构?如果我需要更改列表中的元素,那么应该使用类而不是结构?

解决方案

回答

MyList[1] = new MyStruct("bob");

Csho中的struct几乎总是被设计成不可变的(也就是说,一旦它们被创建,就无法改变其内部状态)。

在情况下,我们要做的是替换指定数组索引中的整个结构,而不是尝试仅更改单个属性或者字段。

回答

不完全的。将类型设计为类或者结构不应由将其存储在集合中的需求所驱动:)我们应该查看所需的"语义"

我们看到的问题是由于值类型语义所致。每个值类型变量/引用都是一个新实例。当你说

Struct obItem = MyList[1];

发生的情况是创建了该结构的新实例,并且所有成员都被一个一个地复制。这样我们就可以克隆MyList [1],即2个实例。
现在,如果我们修改obItem,它不会影响原始对象。

obItem.Name = "Gishu";  // MyList[1].Name still remains "peter"

现在在这里忍受我2分钟(这需要花一会儿时间才能吞下..对我来说确实如此:)
如果确实需要将结构存储在集合中并按照问题中的指示进行修改,则必须使结构公开一个接口(但是这将导致装箱)。然后,我们可以通过引用盒装对象的接口引用来修改实际的结构。

以下代码段说明了我在上面所说的内容

public interface IMyStructModifier
{
    String Name { set; }
}
public struct MyStruct : IMyStructModifier ...

List<Object> obList = new List<object>();
obList.Add(new MyStruct("ABC"));
obList.Add(new MyStruct("DEF"));

MyStruct temp = (MyStruct)obList[1];
temp.Name = "Gishu";
foreach (MyStruct s in obList) // => "ABC", "DEF"
{
    Console.WriteLine(s.Name);
}

IMyStructModifier temp2 = obList[1] as IMyStructModifier;
temp2.Name = "Now Gishu";
foreach (MyStruct s in obList) // => "ABC", "Now Gishu"
{
    Console.WriteLine(s.Name);
}

HTH。好问题。
更新:@Hath,我们让我跑步检查我是否忽略了这么简单的内容。 (如果设置器属性和方法没有使.Net Universe仍然保持平衡,那将是不一致的:)
设置器方法不起作用
obList2 [1]返回其状态将被修改的副本。列表中的原始结构保持不变。因此,"通过接口设置"似乎是唯一的方法。

List<MyStruct> obList2 = new List<MyStruct>();
obList2.Add(new MyStruct("ABC"));
obList2.Add(new MyStruct("DEF"));
obList2[1].SetName("WTH");
foreach (MyStruct s in obList2) // => "ABC", "DEF"
{
    Console.WriteLine(s.Name);
}

回答

结构不是"不可变的"不是很多。

真正的根本问题是结构是值类型,而不是引用类型。因此,当我们从列表中拉出对该结构的"引用"时,它将创建整个结构的新副本。因此,我们对其进行的任何更改都将更改副本,而不是列表中的原始版本。

像安德鲁州一样,我们必须替换整个结构。尽管如此,我认为我们必须问自己,为什么首先要使用结构(而不​​是类)。确保我们没有围绕过早的优化问题进行操作。