根据我的 comments :
首先,您应该判断IEnumerable<T> source
、actually is、IReadOnlyCollection<T>
还是ICollection<T>
,因为它有一个您可以使用的.Count
属性--这比任何迭代都更可取.
假设您的IEnumerable<T>
没有O(1)
.Count
属性,如果您想查看是否有at least 1元素(即"at least 2 or more"),则使用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;
}
如果你想提高even more的效率,允许消费者提供非盒装的枚举数(例如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() ) )
{
}