C#中的List <struct> VS List <class>

时间:2018-07-24 13:35:17

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

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

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

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

对于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时的情况,而我发现{ {1}}是元凶。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

这是由于reference- and value-types semantics造成的。 引用类型(= 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;

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