为什么列表中的结构状态不能改变?

时间:2009-03-26 16:29:21

标签: c#

我知道这听起来很愚蠢。但我必须在这里做错事。

说,

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方式那就太棒了。

5 个答案:

答案 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();

虽然你真的创造了一个全新的名单 - 但这是你的结构。