是否有一种更智能的方法可以保护foreach
循环免受NullReference异常的影响:
if (G_Locatie.OverdrachtFormulierList != null)
{
foreach (OverdrachtFormulier otherform in G_Locatie.OverdrachtFormulierList)
{
...
}
}
我使用了很多foreach循环,经常嵌套,以及很多变量,例如G_Location肯定存在,但是datamember .OverdrachtFormulierList可能尚未被分配使用new
的列表。
亲爱的朋友们,感谢您的所有评论。在了解了你的建议之后,虽然很难理解,但在深入研究Lasagna代码后,我开始研究,经过一些实验,我发现最简单最干净的方法是简单地避免使用NULL,正确初始化。虽然我不得不在我的代码中初始化OverdrachtFormulierList,但有遗忘一个实例的风险,我找到了适当的初始化位置,即在原始类定义中。
为简单起见,请查看以下代码:
class MyClass
{
public List<string> items = new List<string>();
public IEnumerator<string> GetEnumerator()
{
return items.GetEnumerator();
}
}
class MyComplexClass
{
private MyClass _itemlist /*= new MyClass()*/;
public MyClass itemlist
{
get { return _itemlist; }
set { _itemlist = value; }
}
}
void Sandbox()
{
MyClass mc /*= new MyClass()*/;
foreach (string Sb in mc.items)
{
string x = Sb;
}
MyComplexClass mcc = new MyComplexClass();
foreach (string Mb in mcc.itemlist) // <--- NullReferenceException
{
string x = Mb;
}
return;
}
有趣的是,C#似乎可以保护您免受许多错误的错误。如果您不取消注释Sandbox()
中的初始化,则不会构建此代码,因此第一个foreach
将无法获得NullReferenceException
。
但是,您最好在MyComplexClass
中取消注释init,以避免第二个foreach
中的异常。无论是否进行初始化,C#都将构建。
事实证明,在我的实际代码中,我只需要在G_Locatie的Class定义中添加一个简单的初始化。
现在唯一的问题是我一直想用{get; set;}
来简化上面的代码,但是如上所述的初始化是不可能的。我将不得不忍受那个小问题。
事实上,在对象类型属性上,您实际上并不需要setter。
最后,我意识到我无法为我的问题找到合适的标题。到目前为止,我所遇到的每一个问题都已在本论坛中得到解答,我觉得我今天只能发帖,因为我找不到与此类似的帖子。也许有人可以提出标题和标签,使这个解决方案更容易找到。
答案 0 :(得分:6)
是的,您的集合属性应该返回空集合而不是null。确保这一点的一种方法是使用支持字段并在getter中分配新列表:
private List<string> overdrachtFormulierList;
public List<string> OverdrachtFormulierList
{
get
{
return this.overdrachtFormulierList ??
(this.overdrachtFormulierList = new List<string>());
}
set
{
this.overdrachtFormulierList = value;
}
}
如果您的类型为Enumerable.Empty<T>
IEnumerable<T>
答案 1 :(得分:5)
一种选择是创建扩展方法:
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable source)
{
return source ?? Enumerable.Empty<T>();
}
然后:
foreach (var otherform in G_Locatie.OverdrachtFormulierList.EmptyIfNull())
{
...
}
请注意,总是最好使用空集合而不是空引用。