我有以下代码:
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是对Customer of List的引用。不应在列表中的StructCustomer变量中编辑值吗?
我知道Structs是值而不是引用类型,但我将它装入List!
答案 0 :(得分:1)
结构是值类型,因此,当您从列表中检索它们时,如示例中所示,您要检索的是其值的副本。然后你修改。这不会更改列表中包含的原始内容。
如果要更改列表中的元素,请执行以下操作:
listStructs[0].ID = 2;
listStrings[0].name = "Edited by method";
答案 1 :(得分:1)
嗯,当你这样做时:
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使用所推荐的,而是它的出路=)
答案 2 :(得分:1)
创建结构类型列表将导致列表中的每个项目封装结构中的所有字段。列表的索引'get'方法将所有与列表项关联的字段复制到返回值的相应字段中;索引的'put'将所有字段从传入的项复制到与相应列表项关联的相应字段。请注意,'get'和'put'都不会在列表中的项目与读取或写入的项目之间创建任何附件;未来的变化不会影响另一方。
对于许多类型的节目,这种分离有时是可取的,有时不是。为了帮助促进这种情况,我建议创建一个类型:
class SimpleHolder<T> { public T Value; /* A field, not a property! */ }
然后使用List<SimpleHolder<StructCustomer>>
。
您的类应该自己创建每个SimpleHolder<StructCustomer>
实例,并且永远不会将对任何这些实例的引用暴露给外部代码。如果你想要一个方法,例如返回项目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”类可以很容易地结合结构类型和可变类的优点。
答案 3 :(得分:0)
List包含值类型,因此当您向其请求项目时它会返回值。尝试制作一个列表,你会看到相同的行为。
因此,您需要直接对列表中的列表项进行分配。通过在foreach循环中迭代列表,您可以在语义上更接近于您尝试的行为。