Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#LINQ选择多个默认值_C#_Linq_Extension Methods_Func - Fatal编程技术网

C#LINQ选择多个默认值

C#LINQ选择多个默认值,c#,linq,extension-methods,func,C#,Linq,Extension Methods,Func,我正在寻找一个优雅的解决方案,将集合中的子集合聚合为一个大集合。我的问题是某些子集合何时可以为null 例如: var aggregatedChildCollection=parentCollection.SelectMany(x=>x.ChildCollection); 如果任何子集合对象为null,则会引发异常。有些备选方案是: //选项1 var aggregatedChildCollection=parentCollection .Where(x=>x.ChildCollection!

我正在寻找一个优雅的解决方案,将集合中的子集合聚合为一个大集合。我的问题是某些子集合何时可以为null

例如:

var aggregatedChildCollection=parentCollection.SelectMany(x=>x.ChildCollection);
如果任何子集合对象为null,则会引发异常。有些备选方案是:

//选项1
var aggregatedChildCollection=parentCollection
.Where(x=>x.ChildCollection!=null)
.SelectMany(x=>x.ChildCollection);
//选择2
var aggregatedChildCollection=parentCollection
.SelectMany(x=>x.ChildCollection??新类型的ChildCollection[0]);
这两种方法都能奏效,但我正在对父对象上的许多子集合进行某种操作,而且有点不合适

我想创建一个扩展方法,检查集合是否为null,如果为null,则执行选项2所做的操作—添加一个空数组。但我对Func的理解还不足以让我知道如何编写这个扩展方法。我知道我想要的语法是这样的:

var aggregatedChildCollection = parentCollection
    .SelectManyIgnoringNull(x => x.ChildCollection);
var aggregatedChildCollection=parentCollection.SelectManyIgnoringNull(x=>x.ChildCollection);

有一种简单的扩展方法可以实现这一点吗?

您可以使用自定义扩展方法:

public static IEnumerable<TResult> SelectManyIgnoringNull<TSource, TResult>(
    this IEnumerable<TSource> source, 
    Func<TSource, IEnumerable<TResult>> selector)
{
    return source.Select(selector)
        .Where(e => e != null)
        .SelectMany(e => e);
}

如果
ParentCollection
是您自己的类,您还应该能够为该类创建默认构造函数,例如:

public ParentCollection{
    public ParentCollection() {
        ChildCollection = new List<ChildCollection>();
    }
}
公共父集合{
公共收藏(){
ChildCollection=新列表();
}
}
这将防止出现null ref异常,如果其中没有任何内容,则会给出一个空列表。至少这对EF模型是有效的。

您的“选项2”就是我要做的,只是做了一个小小的调整:使用
Enumerable.Empty()
而不是创建一个空数组来减少您正在创建的新对象的数量

我使用一个简单的扩展方法(以*nix实用程序命名)来保持LINQ语法流并减少键入:

public static IEnumerable<T> Touch<T>(this IEnumerable<T> items) =>
    items ?? Enumerable.Empty<T>();

通过使用
SelectMany

公共静态IEnumerable SelectManyNotNull(
此IEnumerable源(函数选择器)
{
foreach(源中的TSource元素)
{
var子元素=选择器(元素);
if(子元素!=null)
foreach(子元素中的TResult子元素)
收益子元素;
}
}

否,很遗憾,我不能保证会填充任何子集合。如果子集合为null,则类不是无效的,我只是想将所有子集合分组到一个集合中,并通过将它们视为空集合来忽略任何null。这是一个很好的解决方案—在我的例子中,我将它与Cory Nelson使用
Enumerable.empty()的答案相结合
不要删除空集合,这样我至少会有一个空集合。这也行得通,但请注意,Cory链接的代码附带了许可证,因此您需要提供属性。感谢这一点-这是一个很好的资源,很有兴趣了解他们是如何做到的。
var aggregatedChildCollection = parentCollection
    .SelectMany(x => x.ChildCollection.Touch());
public static IEnumerable<TResult> SelectManyNotNull<TSource, TResult>(
         this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) 
{
    foreach (TSource element in source)
    {
        var subElements = selector(element);
        if (subElements != null)
            foreach (TResult subElement in subElements )
                yield return subElement;
    }
}