加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – IEnumerable FirstOrEmpty扩展

发布时间:2020-12-16 01:51:43 所属栏目:百科 来源:网络整理
导读:问题 我正在寻找一种方法来实现IEnumerable X的FirstOrEmpty.其中X实现IEnumerable T.基本上,如果谓词与任何内容都不匹配,则返回Enumerable T .Empty.我不想将源参数约束为IEnumerable IEnumerable X或者因为我可能想要传递一些实现IEnumerable X的东西(例如
问题

我正在寻找一种方法来实现IEnumerable< X>的FirstOrEmpty.其中X实现IEnumerable< T>.基本上,如果谓词与任何内容都不匹配,则返回Enumerable< T> .Empty.我不想将源参数约束为IEnumerable< IEnumerable< X>>或者因为我可能想要传递一些实现IEnumerable< X>的东西(例如IEnumerable< IGrouping< bool,X>>).

用法示例

IEnumerable<T> myCollection;
var groupCheck = myCollection.GroupBy(t => t.SomeProp == 23);

var badGroup = groupCheck.FirstOrEmpty(t => !t.Key);
var goodGroup = groupCheck.FirstOrEmpty(t => t.Key);

foreach(T x in badGroup) { ... }
foreach(T x in goodGroup) { ... }

旧方式:

IEnumerable<T> myCollection = ...;
var groupCheck = myCollection.GroupBy(t => t.SomePropOnClassT == 23);

var badGroup = (groupCheck.FirstOrDefault(t => !t.Key) ?? Enumerable<T>.Empty);
var goodGroup = (groupCheck.FirstOrDefault(t => t.Key) ?? Enumerable<T>.Empty);

foreach(T x in badGroup) { ... }
foreach(T x in goodGroup) { ... }

尝试

尝试1:

public static IEnumerable<TResult> FirstOrEmpty<TSource,TResult>(
    this IEnumerable<TSource> source,Func<TSource,bool> predicate) where TSource : IEnumerable<TResult>
{
    TSource tmp = source.FirstOrDefault(predicate);
    if(tmp != null) {
        foreach(TResult x in tmp)
        {
            yield return x; 
        } 
    }
}

尝试2:

public static IEnumerable<TResult> FirstOrEmpty<TSource,bool> predicate) where TSource : IEnumerable<TResult>
{
    TSource tmp = source.FirstOrDefault(predicate);
    return tmp == null ? Enumerable.Empty<TResult>() : tmp;
}

解决方法

你自己的解决方案

public static IEnumerable<TResult> FirstOrEmpty<TSource,bool> predicate
    )
    where TSource : class,IEnumerable<TResult>
{
    return source.FirstOrDefault(predicate) ?? Enumerable.Empty<TResult>();
}

实际上是在工作.我只添加了类约束.这意味着“TSource必须是引用类型”,并且接口可以使用类约束.原因是如果TSource是某个结构,则默认值(TSource)可能不为null.你可以这样称呼它:

var badGroup = groupCheck.FirstOrEmpty<IGrouping<bool,T>,T>(g => !g.Key);
var goodGroup = groupCheck.FirstOrEmpty<IGrouping<bool,T>(g => g.Key);

不幸的是,编译器不够聪明,无法弄清楚类型参数本身,所以你必须在尖括号中提供它们< ...,...>像上面一样.我还没有找到解决方案.

现在,如果您始终将此与IGrouping<,>一起使用,则可能需要使用以下稍微不那么通用的方法:

public static IEnumerable<TResult> FirstOrEmpty<TKey,TResult>(
    this IEnumerable<IGrouping<TKey,TResult>> source,Func<IGrouping<TKey,TResult>,bool> predicate
    )
{
    return source.FirstOrDefault(predicate) ?? Enumerable.Empty<TResult>();
}

这一次是这样的:

var badGroup = groupCheck.FirstOrEmpty<bool,T>(g => !g.Key);
var goodGroup = groupCheck.FirstOrEmpty<bool,T>(g => g.Key);

好消息是,通过这种方法,编译器将推断出你的类型参数,所以:

var badGroup = groupCheck.FirstOrEmpty(g => !g.Key);
var goodGroup = groupCheck.FirstOrEmpty(g => g.Key);

作品.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读