问题
我正在寻找一种方法来实现 FirstOrEmpty
对于 IEnumerable<X>
其中 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, TResult>(
this IEnumerable<TSource> source,
Func<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, TResult>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
where TSource : class, IEnumerable<TResult>
{
return source.FirstOrDefault(predicate) ?? Enumerable.Empty<TResult>();
}
确实有效。我只添加了 class
约束。这意味着“TSource
必须是引用类型”,并且接口(interface)可以使用 class
约束。原因是default(TSource)
可能不是 null
如果TSource
是一些结构。你可以这样调用它:
var badGroup = groupCheck.FirstOrEmpty<IGrouping<bool, T>, T>(g => !g.Key);
var goodGroup = groupCheck.FirstOrEmpty<IGrouping<bool, T>, 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);
有效。
关于c# - IEnumerable FirstOrEmpty 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13751088/