我知道这听起来很愚蠢。但我必须在这里做错事。
说,
struct lala
{
private bool state1;
public lala(bool state1)
{
this.state1 = state1;
}
public void SetState1ToTrue()
{
this.state1 = true;
}
public bool GetState1()
{
return this.state1;
}
}
然后某个地方......
List<lala> lalas = new List<lala>();
lalas.Add(new lala(false));
lalas.Add(new lala(false));
lalas[0].SetState1ToTrue();
// Why is it False???
Console.WriteLine(lalas[0].GetState1());
除了将其更改为:
之外,是否有任何变通方法List<lala> lalas = new List<lala>();
lalas.Add(new lala(false));
lalas.Add(new lala(false));
lala newLala = lalas[0];
newLala.SetState1ToTrue();
lalas[0] = newLala;
// It's True, finally.
Console.WriteLine(lalas[0].GetState1());
看起来很糟糕,不优雅,浪费了2行代码。如果说1行代码中有任何Linq-ish或Functional Programming-ish方式那就太棒了。
答案 0 :(得分:6)
问题出在这一行:
lalas[0].SetState1ToTrue();
第一部分lalas [0]从列表中检索第一个lala,并在隐式变量中作为它的新副本执行。因此,您的SetState1ToTrue在lala上运行,然后立即丢弃,并且列表中的那个保持不变。这与此相同:
lala newLala = lalas[0];
newLala.SetState1ToTrue();
如果你使lala成为一个类而不是一个struct,那么它就变成了一个引用类型,那么临时变量(显式或隐式)就是对列表中lala的引用。
答案 1 :(得分:1)
结构是值类型,因此它们按值传递。这意味着lalas [0]会在lalas中为您提供结构的副本。您正在更改副本,因此原始文件保持不变。
答案 2 :(得分:0)
你的问题是你正在处理一个结构,它是一个值类型,而不是一个类,它是一个引用类型。您期望的行为是引用类型的行为。我建议只是将你的声明改为一个类(只是给出一个简单的例子),你不应该有问题。
答案 3 :(得分:0)
因为struct
始终是值类型,所以它本质上是不可变的。这意味着而不是:
lalas[0].SetState1ToTrue();
你应该这样做:
lalas[0] = lalas[0].SetState1ToTrue();
有excellent article by Jon Skeet详细解释了值类型和引用类型之间的差异。
答案 4 :(得分:0)
不将其更改为类(这可能是正确答案),您要求的Linq-ish方法将使结构不可变,因此“状态更改”方法将返回修改后的版本。这样,你就不会错误地使用它。
struct lala
{
private readonly bool state1; // note: readonly
public lala(bool state1)
{
this.state1 = state1;
}
public lala SetState1ToTrue()
{
return new lala(true); // would copy any other fields, unchanged
}
public bool GetState1()
{
return this.state1;
}
}
然后你可以一次性“改变”整个列表:
List<lala> changed = original.Select(l => l.SetState1ToTrue()).ToList();
虽然你真的创造了一个全新的名单 - 但这是你的结构。