C# 中的列表<struct> VS 列表<class>

List<struct> VS List<class> in C#

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

例如。如果我插入 "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);
}

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

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

//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;

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

这是由于 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;

顺便说一句,结构通常应该是不可变的。因此,每当您打算修改实例状态时,您应该考虑使用 class 而不是结构。要进一步阅读有关不变性的信息,您还可以阅读此 post:Why are C# structs immutable?

您正在创建 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);

听起来您正在重复使用 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);

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

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