【问题标题】:Trying to Understanding structs. Reference by a List<>试图理解结构。列表<>引用
【发布时间】:2013-09-05 01:08:42
【问题描述】:

我有以下代码:

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 是对客户列表的引用。是否应该在 List 的 StructCustomer 变量中编辑值?

我知道结构是值而不是引用类型,但我将它装箱在一个列表中!

【问题讨论】:

    标签: c# .net list struct


    【解决方案1】:

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

    对于许多类型的程序,这种分离有时是可取的,有时是不可取的。为了帮助促进此类情况,我建议创建如下类型:

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

    然后使用List&lt;SimpleHolder&lt;StructCustomer&gt;&gt;。

    您的类应该自己创建每个SimpleHolder&lt;StructCustomer&gt; 实例,并且永远不要将任何这些实例的引用暴露给外部代码。如果你想有一个方法,例如返回项目 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”类可以很容易地结合结构类型和可变类的优点。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        好吧,当你这样做时:

        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使用率推荐,但是,它是一个出路=)

        【讨论】:

          【解决方案4】:

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

          如果要对列表中的元素进行更改,请这样做:

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

          【讨论】:

            猜你喜欢
            • 2017-12-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多