保护foreach循环不为空的更智能的方法

本文关键字:智能 方法 foreach 循环 保护 | 更新日期: 2023-09-27 18:03:52

是否有一种更聪明的方法来保护foreach循环免受NullReference异常的影响:

if (G_Locatie.OverdrachtFormulierList != null)
{
    foreach (OverdrachtFormulier otherform in G_Locatie.OverdrachtFormulierList)
    {
        ...
    }
}

我使用了很多foreach循环,通常是嵌套的,还有很多变量,比如G_Location确实存在,但是datammember . overdrachtformulierlist可能还没有被分配一个list use 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。

最后,我意识到我找不到一个合适的题目来描述我的问题。到目前为止,我遇到的每一个问题都已经在这个论坛上得到了解答,我觉得我今天不得不发帖只是因为我找不到类似的帖子。也许有人能想出标题和标签,使这个解决方案更容易找到。

保护foreach循环不为空的更智能的方法

是的,你的集合属性应该返回空集合而不是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>

一个选择是创建一个扩展方法:

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable source)
{
    return source ?? Enumerable.Empty<T>();
}

:

foreach (var otherform in G_Locatie.OverdrachtFormulierList.EmptyIfNull())
{
    ...
}

请注意,始终使用空集合比使用空引用更可取。