试图理解结构。由List<>引用

时间:2013-09-02 01:14:42

标签: c# .net list struct

我有以下代码:

public void Start()
    {
        List<StructCustomer> listCustomer = new List<StructCustomer>();

        listCustomer.Add(
            new StructCustomer { ID = 0, name = "Any Default Name", birthday = DateTime.Now });


        DoSomethingWithStructList(listCustomer);
        StructCustomer customer = listCustomer.First();
        Console.WriteLine("ID = {0}, Name = {1}", customer.ID, customer.name); // Writes ID = 0, Name = "Any Default Name"

    }

public void DoSomethingWithStructList(List<StructCustomer> listStructs)
        {
            StructCustomer test = listStructs.First();
            test.ID = 2;
            test.name = "Edited by method";
            Console.WriteLine("ID = {0}, Name = {1}", test.ID, test.name); // Writes "ID = 2, Name = Edited by method"
        }

 public struct StructCustomer
        {
            public int ID { get; set; }
            public string name { get; set; }
            public DateTime birthday { get; set; }
        }

您可以注意到,变量List是对Customer of List的引用。不应在列表中的StructCustomer变量中编辑值吗?

我知道Structs是值而不是引用类型,但我将它装入List!

4 个答案:

答案 0 :(得分:1)

结构是值类型,因此,当您从列表中检索它们时,如示例中所示,您要检索的是其值的副本。然后你修改。这不会更改列表中包含的原始内容。

如果要更改列表中的元素,请执行以下操作:

listStructs[0].ID = 2;
listStrings[0].name = "Edited by method";

答案 1 :(得分:1)

嗯,当你这样做时:

StructCustomer test = listStructs.First();
test.ID = 2;
test.name = "Edited by method";
Console.WriteLine("ID = {0}, Name = {1}", test.ID, test.name);

您实际上是在listStructs中创建第一个结构的副本,因此,您将更改副本的值,而不是真实的值。尝试这样做 - 它应该有效:

listStructs.First().ID = 2;
listStructs.First().name = "Edited by method";

所以,就是这样;) OBS:这种方法不是由CPU使用所推荐的,而是它的出路=)

答案 2 :(得分:1)

创建结构类型列表将导致列表中的每个项目封装结构中的所有字段。列表的索引'get'方法将所有与列表项关联的字段复制到返回值的相应字段中;索引的'put'将所有字段从传入的项复制到与相应列表项关联的相应字段。请注意,'get'和'put'都不会在列表中的项目与读取或写入的项目之间创建任何附件;未来的变化不会影响另一方。

对于许多类型的节目,这种分离有时是可取的,有时不是。为了帮助促进这种情况,我建议创建一个类型:

class SimpleHolder<T> { public T Value; /* A field, not a property! */ }

然后使用List<SimpleHolder<StructCustomer>>

您的类应该自己创建每个SimpleHolder<StructCustomer>实例,并且永远不会将对任何这些实例的引用暴露给外部代码。如果你想要一个方法,例如返回项目0,使用:

StructCustomer FirstCustomer()
{ 
  return listStructHolders[0].Value;
}

存储传入的值:

void AddCustomer(StructCustomer newCustomer)
{
  var temp = new SimpleHolder<StructCustomer>();
  temp.Value = newCustomer;
  listStructHolders.Add(temp);
}

修改客户3的名称:

listStructHolder[3].Value.name = "Fred";

使用简单的“exposed-field holder”类可以很容易地结合结构类型和可变类的优点。

答案 3 :(得分:0)

List包含值类型,因此当您向其请求项目时它会返回值。尝试制作一个列表,你会看到相同的行为。

因此,您需要直接对列表中的列表项进行分配。通过在foreach循环中迭代列表,您可以在语义上更接近于您尝试的行为。