【问题标题】:C# foreaching through list<struct> won't change valuesC# foreaching 通过 list<struct> 不会改变值
【发布时间】:2016-03-04 14:41:41
【问题描述】:

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

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(&amp;h); 但如果我的猜测是正确的 - 我该如何解决这个问题?

【问题讨论】:

  • 问题不在于foreach 本身——而是你使用了可变结构。 不要那样做。除此之外,当您没有显示可能导致问题的循环时,很难看出哪里出了问题。请包含minimal reproducible example,然后停止使用可变结构...
  • C++ != C#。换句话说,在您真正了解差异并需要任何可能获得的性能改进之前,您通常不应该在 C# 中使用 struct
  • @PhillipH:嗯,我们怀疑是这样的。但是我们看不到代码,这使得很难确定。 (这在CheckValue 中肯定是个问题,诚然。)但我 非常确定的是,如果你避免使用可变结构(和公共字段!),就很难进入这种情况。
  • 我也强烈建议您也开始遵循 .NET 命名约定...
  • 归结为:可变结构是邪恶的

标签: c# foreach addressing


【解决方案1】:

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

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

解决办法是把hintStructure改成class:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-10-15
      • 2021-03-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      • 2012-02-14
      相关资源
      最近更新 更多