我有一个简单的课程:
private class ColumnAndValue
{
private string columnName;
private string columnValue;
public string ColumnName
{
get { return columnName; }
set { columnName = value.Trim(); }
}
public string ColumnValue
{
get { return columnValue; }
set { columnValue = value.Trim(); }
}
}
该班级列表:
private List<ColumnAndValue> cvList = new List<ColumnAndValue>();
这是我的问题所在,当我尝试加载列表时,我的值就会出现。这是我加载它的方式:
public void TestList()
{
ColumnAndValue cv = new ColumnAndValue();
cv.ColumnName = "Column 1";
cv.ColumnValue = "Value 1";
cvList.Add(cv);
cv.ColumnName = "Column 2";
cv.ColumnValue = "Value 2";
cvList.Add(cv);
cv.ColumnName = "Column 3";
cv.ColumnValue = "Value 3";
cvList.Add(cv);
cv.ColumnName = "Column 4";
cv.ColumnValue = "Value 4";
cvList.Add(cv);
List<string> c1 = new List<string>();
c1 = cvList.Select(c => c.ColumnName).ToList();
foreach (object obj in c1)
{
Console.WriteLine(obj.ToString());
}
}
当我运行此代码时,我得到四次迭代:
Column 4
Column 4
Column 4
Column 4
当我在调试时进入每个cvList.Add时,第一次迭代显示带有正确信息的cvList,第二次两个值都有第2列......所以,我试过这样:
ColumnAndValue cv1 = new ColumnAndValue();
ColumnAndValue cv2 = new ColumnAndValue();
ColumnAndValue cv3 = new ColumnAndValue();
ColumnAndValue cv4 = new ColumnAndValue();
cv1.ColumnName = "Column 1";
cv1.ColumnValue = "Value 1";
cvList.Add(cv1);
cv2.ColumnName = "Column 2";
cv2.ColumnValue = "Value 2";
cvList.Add(cv2);
cv3.ColumnName = "Column 3";
cv3.ColumnValue = "Value 3";
cvList.Add(cv3);
cv4.ColumnName = "Column 4";
cv4.ColumnValue = "Value 4";
cvList.Add(cv4);
一切都按预期发布:
Column 1
Column 2
Column 3
Column 4
我的问题是,如何只使用一个cv实例填充列表?
答案 0 :(得分:3)
将其更改为:
public void TestList()
{
cvList.Add(new ColumnAndValue(){ColumnName = "Column 1", ColumnValue = "Value 1"});
cvList.Add(new ColumnAndValue(){ColumnName = "Column 2", ColumnValue = "Value 2"});
cvList.Add(new ColumnAndValue(){ColumnName = "Column 3", ColumnValue = "Value 3"});
cvList.Add(new ColumnAndValue(){ColumnName = "Column 4", ColumnValue = "Value 4"});
List<string> c1 = cvList.Select(c => c.ColumnName).ToList();
foreach (object obj in c1)
{
Console.WriteLine(obj.ToString());
}
}
因为List.Add()添加对ColumnAndValue
实例的引用而不是副本,因此,如果更改对象的名称,它将在您使用它的所有位置更改。
您可以在MSDN上的When is a C# value/object copied and when is its reference copied?和Value Types and Reference Types
了解更多相关信息答案 1 :(得分:2)
每次都需要新建你的简历
public void TestList()
{
ColumnAndValue cv = new ColumnAndValue();
cv.ColumnName = "Column 1";
cv.ColumnValue = "Value 1";
cvList.Add(cv);
cv = new ColumnAndValue();
cv.ColumnName = "Column 2";
cv.ColumnValue = "Value 2";
cvList.Add(cv);
cv = new ColumnAndValue();
cv.ColumnName = "Column 3";
cv.ColumnValue = "Value 3";
cvList.Add(cv);
cv = new ColumnAndValue();
cv.ColumnName = "Column 4";
cv.ColumnValue = "Value 4";
cvList.Add(cv);
List<string> c1 = new List<string>();
c1 = cvList.Select(c => c.ColumnName).ToList();
foreach (object obj in c1)
{
Console.WriteLine(obj.ToString());
}
}
cv是对象的句柄。如果你不是每次都新建它,你只是改变同一个对象的值。你的cvlist只引用了同一个对象,每次都会更新
答案 2 :(得分:2)
发生的事情是,您的List
实际上是您已创建的同一对象的引用列表。您不断更改同一对象中的数据,但不断在列表中添加对它的引用。
有关详细信息,请check the difference between reference types and value types。
编辑:这个效果有一个答案,但由于某种原因被删除了。您期望的行为是值类型,它是使用struct
关键字定义的。值类型按值复制。因此,在您的代码中,将class
更改为struct
会执行您期望的行为。 请记住它仍然是奇怪的代码,您应该习惯使用新数据实现新对象,因为您的代码将更具可读性。改变现有对象中的数据(即Mutability)的能力是一个强大的工具,但是如你刚才发现的那样,使用它很容易被滥用和出错。
答案 3 :(得分:1)
您应该使用新实例。如果您将项目添加到列表,然后更改项目属性,您只是编辑相同的项目。再次将其添加到列表中只会添加对该项目的另一个引用。
这是一种简单的方法:
private class ColumnAndValue
{
private string columnName;
private string columnValue;
public string ColumnName
{
get { return columnName; }
set { columnName = value.Trim(); }
}
public string ColumnValue
{
get { return columnValue; }
set { columnValue = value.Trim(); }
}
public ColumnAndValue(string colName, string colValue)
{
columnName = colName;
columnValue = colValue;
}
}
然后使用以下方式创建列表:
private List<ColumnAndValue> cvList = new List<ColumnAndValue>();
cvList.Add(new ColumnAndValue("Column 1", "Value 1"));
cvList.Add(new ColumnAndValue("Column 2", "Value 2"));
cvList.Add(new ColumnAndValue("Column 3", "Value 3"));
cvList.Add(new ColumnAndValue("Column 4", "Value 4"));
答案 4 :(得分:1)
您看,ListT.Add方法不会创建其引用参数的副本。它只是复制并存储对您的类(相同)实例的引用四次。
这是ListT.Add referencesource.microsoft.com
的代码您的问题是矛盾的,如果您只想要一个实例,那么您只能获得一个实例。 ListT.Add不复制(不创建引用类型的实例)。
答案 5 :(得分:1)
将cv对象添加到列表中时,列表会为该对象维护引用。
这意味着您反复将同一个对象添加到列表中,并更改同一个对象。
您要做的是在列表中添加不同的变量:
public void TestList()
{
ColumnAndValue cv = new ColumnAndValue();
cv.ColumnName = "Column 1";
cv.ColumnValue = "Value 1";
cvList.Add(cv);
// Now cv is a reference to a different object
cv = new ColumnAndValue();
cv.ColumnName = "Column 2";
cv.ColumnValue = "Value 2";
cvList.Add(cv);
// Now cv is a reference to a different object
cv = new ColumnAndValue();
cv.ColumnName = "Column 3";
cv.ColumnValue = "Value 3";
cvList.Add(cv);
// Now cv is a reference to a different object
cv = new ColumnAndValue();
cv.ColumnName = "Column 4";
cv.ColumnValue = "Value 4";
cvList.Add(cv);
List<string> c1 = new List<string>();
c1 = cvList.Select(c => c.ColumnName).ToList();
foreach (object obj in c1)
{
Console.WriteLine(obj.ToString());
}
}