c# – IEnumerable FirstOrEmpty扩展
问题
我正在寻找一种方法来实现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); 作品. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |