仅当第二个 TSource 不为 Null 时才联合集合

ins*_*ide 1 .net c# linq ienumerable

我有以下 linq 语句:

List<Type> allTypes = group.GetTypes().Union(group2.GetTypes()).ToList();
Run Code Online (Sandbox Code Playgroud)

可能存在 group2 为 null 的情况,这会抛出 NullReferenceException

解决此问题的一种方法是之前执行空检查,例如:

if (group2 != null)
{
    List<Type> allTypes = group.GetTypes().Union(group2.GetTypes()).ToList();
}
else 
{
   List<Type> allTypes = group.GetTypes();
}
Run Code Online (Sandbox Code Playgroud)

但问题是我对不同类型有许多类似的赋值,并且不想以这种方式为每个类型执行 if 语句,但我宁愿将空检查放在一行中,例如:

 List<Type> allTypes = group.GetTypes().Union((if group2 != null)group2.GetTypes()).ToList();
Run Code Online (Sandbox Code Playgroud)

但不知道如何用 linq 做到这一点。

gwi*_*rrr 5

您在这里遇到的问题不是 TSource 为空;您想要从中获取源的对象是 null ( group2)。

您可以随时使用Enumerable.Empty来保存您的魔法一号衬垫。

List<Type> allTypes = group.GetTypes().Union(group2 != null ? group2.GetTypes() : Enumerable.Empty<Type>()).ToList();
Run Code Online (Sandbox Code Playgroud)

或者您可以使用可重用的Union重载:

public static IEnumerable<T> Union<T>(this IEnumerable<IEnumerable<T>> source)
{
    var set = new HashSet<T>();
    foreach (var s in source)
    {
       foreach (var item in s)
       {
           if (set.Add(item))
               yield return item;
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码变成:

var allTypes = new [] { group, group2 }.Where(x => x != null).Select(x => x.GetTypes()).Union().ToList();
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是可以有两个以上的序列形成联合。