C#foreaching through list <struct>不会改变值

时间:2016-03-04 14:41:41

标签: c# foreach addressing

我有一个结构保持条件信息。

private struct hintStructure
{
    public string id;
    public float  value;
    public bool   alreadyWarned;
}
private List<hintStructure> hints;

每当我的程序更改一个值时,就会发送一个事件并检查条件列表是否符合条件。

public void EventListener (string id)
{
    CheckHints(id); //id of the updated element
}

private void CheckHints(string _id) 
{
    foreach (hintStructure _h in hints)
        if (_h.id == _id) CheckValue(_h);
}

private void CheckValue(hintStructure _h)
{
    float _f = GetValue(_h.id);

    if (_f < _h.value)
    {
        ActivateHint(_h);
        _h.alreadyWarned = true;
    }
    else 
        _h.alreadyWarned = false;
}

private void ActivateHint(hintStructure _h)
{
    if(_h.alreadyWarned == false)
        ShowPopup();
}

ShowPopup()只应在未显示该特定元素时显示(由bool alreadyWarned表示)。问题是:它总是显示出来。似乎调用了行_h.alreadyWarned = true;,但是没有存储该值(我检查它是否被调用,确实如此)。 我认为foreach可能是问题(因为它在几年前就出现了问题),但它也不适用于for()结构。

我的最后一个猜测是解决问题, C ++ 中的典型问题: CheckValue(h); vs. CheckValue(&h);但如果我对这个猜测是正确的 - 我该如何解决这个问题?

2 个答案:

答案 0 :(得分:5)

您正在传递结构,而不是类实例。对结构的更改(未作为ref传递)正在更改结构的本地副本。您正在尝试将结构化作为引用类型。

对函数中的结构所做的更改不会更改原始结构的值 - 在将结构传递给函数之前将结构复制到堆栈中。

答案 1 :(得分:5)

问题是 C#中的结构是值类型,因此当您致电CheckValue(_h)时,您正在创建_h的副本并且该副本已更新,但原始版本在清单保持不变。

经典解决方案是通过引用(ref)传递此实例,但您无法使用foreach变量执行此操作。

解决方案是将hintStructure更改为class:

private class Hint
{
    public string id;
    public float  value;
    public bool   alreadyWarned;
}