【问题标题】:List<struct> VS List<class> in C# [duplicate]C# 中的 List<struct> VS List<class> [重复]
【发布时间】:2018-07-24 13:35:16
【问题描述】:

我根据结构创建了一个列表,但无法更改项目值。所以我使用了一个类而不是结构,但是当我打印列表时出现问题,它根据项目的数量给了我插入的最新项目。

例如。如果我插入 "A" , "B" , "C" 那么输出将是 C C C 而不是 A B C

代码如下:

public struct Item     //this is working fine but can't change item price
{
    public string Code { get; set; }
    public string Description{ get; set; }
    public string Price{ get; set; }
    public string Qty { get; set; }
}

public static Class Item   //this is not working it's overwrite the last value
{
    public string Code { get; set; }
    public string Description{ get; set; }
    public string Price{ get; set; }
    public string Qty { get; set; }
}

其余代码

public static Item xItem = new Item();
public static List<Item> item = new List<Item>();

xItem.Code = txtCode.Text;
xItem.Description = txtDescription.text;
xItem.Price= txtPrice.text;
xItem.Qty = txtQty.text;

这两种方法我都试过了(结果相同)

item.Insert(i,xItem);
// and
item.Add(xItem);

btnSave_Click我添加了这个

foreach (var s in item)
{
  System.Diagnostics.Debug.WriteLine(s.Code +" \t " + s.Qty);
}

【问题讨论】:

  • 抱歉,现已更新。
  • 你应该看看引用类型(=classes)和值类型(=structs)。顾名思义,引用类型是对完全相同实例的引用,而在值类型上,您每次将实例传递给方法时都会复制该实例。
  • 你可能不应该使用struct,除非你已经阅读了它,直到现在坚持使用class
  • 您的基于类的代码中有多少次new Item()?这就是您创建的Item 的实际实例数。您可能对单个实例有多个引用,我怀疑我的问题的答案是 1 - 所以您的列表中存储了 3 个引用,但它们都引用了同一个实例。
  • 您只创建一个对象并将其 3 个引用放入同一个列表中。您需要新建 3 个对象。

标签: c# asp.net visual-studio c#-4.0 c#-3.0


【解决方案1】:

听起来您正在重新使用xItem 对象。 您需要为列表中的每个项目创建一个新项目。该列表只是对象引用的列表,目前它们都指向相同的实际对象。 例如这段代码:

public static Item xItem = new Item();
public static List<Item> list = new List<Item>();

xItem.Code = "A";
xItem.Description = "A";
xItem.Price= "1";
xItem.Qty = "1";

list.Add(xItem);
//list now has 'A' with value of 1 in it..

xItem.Code = "B"
//without any further change, list will now have the same 
//item, so its Code will now be "B":
//this will be TRUE:
var listIsNowB = (list[0].Code == "B");

相反,您需要这样做:

xItem.Code = "A";
xItem.Description = "A";
xItem.Price= "1";
xItem.Qty = "1";

list.Add(xItem);

//we're now done with that *instance* of Item, so we now create a *new* one.
//we can re-use our variable without problem though.
xItem = new Item();
xItem.Code = "B";
xItem.Description = "B";
xItem.Price= "2";
xItem.Qty = "2";
//xItem is a new object, so this will work as you expect now.
list.Add(xItem);

【讨论】:

    【解决方案2】:

    这是由于reference- and value-types semanticsreference-type (=class) 只是一个指向实例的指针。因此,当您将对象传递给方法时,您实际上提供了指向该对象的指针,而不是实际的对象。您通过该引用更改的所有内容都会反映在对该实例的所有引用上。

    在您的情况下,您只有一个用于不同实例语义的引用。因此创建一个新实例而不是重新使用现有实例:

    public static Item xItem = new Item();
    public static List<Item> item = new List<Item>();
    

    ...

    xItem = new Item();
    xItem.Code = txtCode.Text;
    xItem.Description = txtDescription.text;
    xItem.Price= txtPrice.text;
    xItem.Qty = txtQty.text;
    

    顺便说一句,结构通常应该是不可变的。因此,每当您打算修改实例状态时,您应该考虑使用类而不是结构。如需进一步了解 immutablilty,您还可以阅读这篇文章:Why are C# structs immutable?

    【讨论】:

    • 只是提到'struct' 是可变的有充分的理由。出于性能原因,‘ValueTuple’是可变的。还有更好的理由使静态变量不可变和只读..
    • @FilipCordas 你说得对,启用可变结构可能是有原因的,这就是我通常编写的原因。然而,纯粹的性能通常是一个不好的理由。而是考虑底层的语义
    • 我更担心他使用的那个静态变量。这看起来就像一场等待发生的灾难。如果他使任何东西不可变,他应该完全删除它。此外,我认为你应该使用结构的唯一原因是性能,如果你对性能下降没问题,只需使用一个类。
    【解决方案3】:

    您正在创建 Item 的静态实例并将其命名为 xItem
    然后设置xItem 的属性并将其添加到您的列表中 - item

    item 现在包含 1 项 - xItem

    然后您再次设置xItem 的属性 - 并再次添加到列表中。
    这就是问题所在。您的列表现在包含 2 个项目 - 2 个对 xItem 的引用 - 不是 2 个不同的对象,而是同一个对象,两次。

    ...又是第三次。

    您的代码需要更改为:

    public static List<Item> item = new List<Item>();
    
    //repeat this for each instance / 'version' of `Item` you want to add to your list.
    // note the `new` keyword
    
    var xItem = new Item();
    xItem.Code = txtCode.Text;
    xItem.Description = txtDescription.text;
    xItem.Price= txtPrice.text;
    xItem.Qty = txtQty.text;
    item.Add(xItem);
    

    【讨论】:

      【解决方案4】:

      class 是一个引用类型,所以如果你调用一个方法 if 只会将引用传递给对象。 struct 是一种值类型,这意味着当您调用方法时它将创建对象的完整副本,除非您使用inref 调用它。 您需要做的是在每次插入时创建该类的新实例。 像这样

          item.Add(new Item
          {
              Code = txtCode.Text,
              ...
          });
      

      【讨论】:

        【解决方案5】:

        对于struct 版本...没有理由不能更改结构中的值。你能更完整地解释你在那里遇到的问题吗?我怀疑这与使用static 有关,这似乎在这里没有位置......但问题中没有足够的信息让我们确定。

        对于class 版本,您需要在每次要添加条目时创建一个 Item 实例:

        //why are these static? That seems like a bad idea, but we lack enough context to know for sure
        public static Item xItem;
        public static List<Item> item = new List<Item>();
        
        xItem = new Item();
        xItem.Code = txtCode.Text;
        xItem.Description = txtDescription.text;
        xItem.Price= txtPrice.text;
        xItem.Qty = txtQty.text;
        

        这将允许您将多个类实例添加到列表中...但是如果我的怀疑是正确的,那么您将处于与使用 struct 时相同的情况,我发现它很可能是 static是罪魁祸首。

        【讨论】:

          猜你喜欢
          • 2014-05-26
          • 1970-01-01
          • 2021-12-19
          • 2021-04-04
          • 1970-01-01
          • 1970-01-01
          • 2011-08-17
          • 2011-09-29
          • 2016-11-17
          相关资源
          最近更新 更多