guh*_*hou 22 c# linq extension-methods
我要检查一个IEnumerable包含正好一个元素.这个片段确实有效:
bool hasOneElement = seq.Count() == 1
Run Code Online (Sandbox Code Playgroud)
然而,它并不是非常有效,因为Count()它将枚举整个列表.显然,知道列表是空的或包含多于1个元素意味着它不是空的.是否存在具有此短路行为的扩展方法?
Jon*_*eet 20
这应该这样做:
public static bool ContainsExactlyOneItem<T>(this IEnumerable<T> source)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
// Check we've got at least one item
if (!iterator.MoveNext())
{
return false;
}
// Check we've got no more
return !iterator.MoveNext();
}
}
Run Code Online (Sandbox Code Playgroud)
你可以进一步忽视这一点,但我不建议你这样做:
public static bool ContainsExactlyOneItem<T>(this IEnumerable<T> source)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
return iterator.MoveNext() && !iterator.MoveNext();
}
}
Run Code Online (Sandbox Code Playgroud)
这是一种时髦的技巧,但可能不应该在生产代码中使用.这还不够清楚.事实上,在RHS工作正常的情况下,&&运算符的LHS中的副作用是令人讨厌的......虽然很有趣;)
编辑:我刚刚看到你提出完全相同的东西,但任意长度.你的最终回复陈述是错误的 - 它应该是回归!en.MoveNext().这是一个完整的方法,具有更好的名称(IMO),参数检查和优化ICollection/ ICollection<T>:
public static bool CountEquals<T>(this IEnumerable<T> source, int count)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count",
"count must not be negative");
}
// We don't rely on the optimizations in LINQ to Objects here, as
// they have changed between versions.
ICollection<T> genericCollection = source as ICollection<T>;
if (genericCollection != null)
{
return genericCollection.Count == count;
}
ICollection nonGenericCollection = source as ICollection;
if (nonGenericCollection != null)
{
return nonGenericCollection.Count == count;
}
// Okay, we're finally ready to do the actual work...
using (IEnumerator<T> iterator = source.GetEnumerator())
{
for (int i = 0; i < count; i++)
{
if (!iterator.MoveNext())
{
return false;
}
}
// Check we've got no more
return !iterator.MoveNext();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:现在对于功能性粉丝来说,是一种递归形式CountEquals(请不要使用它,它只是在这里咯咯笑):
public static bool CountEquals<T>(this IEnumerable<T> source, int count)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count",
"count must not be negative");
}
using (IEnumerator<T> iterator = source.GetEnumerator())
{
return IteratorCountEquals(iterator, count);
}
}
private static bool IteratorCountEquals<T>(IEnumerator<T> iterator, int count)
{
return count == 0 ? !iterator.MoveNext()
: iterator.MoveNext() && IteratorCountEquals(iterator, count - 1);
}
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,对于像LINQ to SQL这样的东西,你应该使用简单的Count()方法 - 因为这将允许它在数据库中完成而不是在获取实际结果之后.
不,但你可以自己写一个:
public static bool HasExactly<T>(this IEnumerable<T> source, int count)
{
if(source == null)
throw new ArgumentNullException("source");
if(count < 0)
return false;
return source.Take(count + 1).Count() == count;
}
Run Code Online (Sandbox Code Playgroud)
编辑:在澄清之后从至少 改为完全改变.
为了更全面和有效的解决方案(只使用1枚举并检查序列实现ICollection或ICollection<T>在这种情况下枚举是没有必要的),你可能想看看我的答案在这里,它可以让你指定你是否正在寻找Exact,AtLeast或AtMost测试.
| 归档时间: |
|
| 查看次数: |
1228 次 |
| 最近记录: |