在C#中,使用Linq,如果我想检查集合是否有任何元素,我可以这样做:
someCollection.Any()
这比更可取
someCollection.Count() > 0
由于后者会统计集合中的所有项目,所以当我真的不在乎有多少项目时,我只想知道是否有。
是否有相应的方法来检查集合是否有多个项目?类似于:
someCollection.Many()
而不是必须进行
someCollection.Count() > 1
我知道这是个愚蠢的问题,从我的研究来看,它看起来并没有。但由于这是我经常使用的东西,我想我应该与社区核实一下。
感谢
根据我的评论:
首先,您应该检查IEnumerable<T> source
是否真的是IReadOnlyCollection<T>
或ICollection<T>
,因为它具有可以使用的.Count
属性,这比任何迭代都更可取。
假设您的IEnumerable<T>
没有O(1)
.Count
属性,如果您想查看是否至少有个1元素(即">至少2个或更多"(,则使用source.Take(2).Count() == 2
或source.Skip(1).Any()
。
像这样:
public static Boolean Many<T>( this IEnumerable<T> source )
{
if( source is null ) throw new ArgumentNullException(nameof(source));
if( source is ICollection<T> col ) return col.Count >= 2;
else if( source is IReadOnlyCollection<T> roCol ) return roCol.Count >= 2;
return source.Take(2).Count() == 2;
}
如果你想提高效率,可以手动迭代:
public static Boolean Many<T>( this IEnumerable<T> source )
{
if( source is null ) throw new ArgumentNullException(nameof(source));
if( source is ICollection<T> col ) return col.Count >= 2;
else if( source is IReadOnlyCollection<T> roCol ) return roCol.Count >= 2;
Int32 count = 0;
using( IEnumerator<T> iter = source.GetEnumerator() )
{
while( iter.MoveNext() && count < 2 )
{
count += 1;
}
}
return count == 2;
}
如果您想提高的效率,请允许消费者提供非盒装枚举器(例如List<T>.Enumerator
(:
public static Boolean Many<TEnumerable,TEnumerator,TElement>( /*this*/ TEnumerable source, Func<TEnumerable,TEnumerator> getEnumerator )
where TEnumerable : IEnumerable<TElement>
where TEnumerator : IEnumerator<TElement>
{
if( source is null ) throw new ArgumentNullException(nameof(source));
if( getEnumerator is null ) throw new ArgumentNullException(nameof(getEnumerator));
//
if ( source is ICollection<TElement> col ) return col .Count >= 2;
else if( source is IReadOnlyCollection<TElement> roCol ) return roCol.Count >= 2;
Int32 count = 0;
using( TEnumerator iter = getEnumerator( source ) )
{
while( iter.MoveNext() && count < 2 )
{
count += 1;
}
}
return count == 2;
}
像这样使用:
List<String> listOfStrings = new List<String>() { ... };
if( listOfStrings.Many</*TEnumerable:*/ List<String>, /*TEnumerator:*/ List<String>.Enumerator, /*TElement:*/ String >( l => l.GetEnumerator() ) )
{
}
- 是的,很难看。。。不幸的是,C#仍然不支持这种级别的泛型类型推理,也不支持部分泛型参数应用
list.GetEnumerator()
部分是必需的,因为它是将基于struct
的枚举器传递到泛型代码中而不装箱(至少不是无反射(的唯一方法