如何替换列表模型中的可空对象?

时间:2016-03-18 14:28:24

标签: c# .net

源代码中存在一个奇怪的错误,它会实例化一个随机变为null的新类。坏部分是将空对象分配给列表模型。所以,我试图用错误对象替换null对象而没有运气。

我收到此错误消息

  

System.ArgumentOutOfRangeException:索引超出范围。在尝试替换null对象时,必须是非负的且小于集合的大小。

那么,你如何解决这个问题?

public class Foo
{
    public bool ErrorFlag { get; set; }
}

//Sample to produce the bug...
var modelFoos = new List<Foo>();
modelFoos.Add(new Foo() { ErrorFlag = false; } );
modelFoos.Add(new Foo() { ErrorFlag = false; } );
modelFoos.Add(null);  //This happen when strange bug occurred
modelFoos.Add(new Foo() { ErrorFlag = false; } );
modelFoos.Add(new Foo() { ErrorFlag = false; } );

for(var x = 0; x < modelFoos.Count; x++)
{
    if (modelFoos[x] == null)
    {
        var foo = new Foo() { ErrorFlag = true; };
        modelFoos[x] = foo;  //This is where I get exception error
    }
}

3 个答案:

答案 0 :(得分:4)

有两件事告诉我,这里有多线程,另一个线程正在修改这个列表,而你正在对它进行操作。

首先是:

  

随机变为空

如果它看起来是随机的,而您正在处理的代码并未对其进行更改,那么可能会在另一个帖子中进行更改。

但这里有更大的旗帜:

if (modelFoos[x] == null)
{
    var foo = new Foo() { ErrorFlag = true; };
    modelFoos[x] = foo;  //This is where I get exception error
}

当您检查空值时,索引不会超出范围,但稍后会超出范围。这意味着列表中的项目数在这两行代码之间发生了变化,而不是 by 该代码。

这两个标志似乎表明另一个线程上的某些东西正在对同一个集合进行更改。

如果您提供更完整的代码示例,可能会有所帮助。看起来您试图将其简化为在此处发布,但相关细节可能会丢失。该列表是从其他地方传递到该方法还是实际上是在此方法中创建的?我的猜测是它被传入了,所以还有其他引用同一个列表,其他东西正在修改。

答案 1 :(得分:1)

如果您的代码在并行任务中运行,只需使用lock Statement来阻止 这个问题。

  

lock关键字确保一个线程不会输入关键字   代码段,而另一个线程在临界区。如果   另一个线程试图输入一个锁定的代码,它会等待,阻止,   直到对象被释放。

private Object thisLock = new Object();

lock (thisLock)
{
   foreach(var x = 0; x < modelFoos.Count; x++)
   {
    if (modelFoos[x] == null)
    {
        var foo = new Foo() { ErrorFlag = true; };
        modelFoos[x] = foo;
    }
  }
}

答案 2 :(得分:0)

使用 for(var x = 0; x < modelFoos.Count; x++) 而不是for(var x = 0; x <= modelFoos.Count; x++)

你在那个循环中走得太远了。