相当于 Linq 的 Any() 函数,当集合有多个项目时



在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() == 2source.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的枚举器传递到泛型代码中而不装箱(至少不是无反射(的唯一方法

最新更新