categories.Contains
仅当 Categories属性为空时,此代码才会抛出 NRE 。
以下代码将抛出:
class Token
{
public string[] Categories{get;set;}
}
var tokens=new []{new Token()};
var categories = tokens.SelectMany(x => x.Categories);
if (categories != null)
{
if (categories.Contains("interp"))
{
Console.WriteLine("Found");
}
}
但也会如此
tokens.SelectMany(x => x.Categories).ToArray();
实际抛出的是SelectMany中的嵌套迭代器,而不是ToArray()
or Contains
。该异常的堆栈跟踪是:
at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
at System.Linq.Enumerable.Contains[TSource](IEnumerable`1 source, TSource value, IEqualityComparer`1 comparer)
at UserQuery.Main()
SelectMany
将尝试遍历每个Categories
条目,发现该属性实际上为 null 并抛出。
快速解决方法是添加一个Where
beforeSelectMany
以消除 null Categories :
var categories = tokens.Where(x=>x.Categories!=null).SelectMany(x => x.Categories);
真正的解决方案是确保Categories
永远不会为空 - 它应该在构造时初始化为空数组、列表等。重新分配时,绝不应将其设置为 null。
此示例将_categories
字段设置为new string[0]
即使调用者传递null
给类别
class Token
{
string[] _categories=new string[0];
public string[] Categories{
get => _categories;
set => _categories = value??new string[0];
}
}
有了它,Where(x=>x.Categories !=null)
就不再需要了