You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
258 lines
7.6 KiB
258 lines
7.6 KiB
5 years ago
|
// Needed for NET40
|
||
|
#if !NET_4_6
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace LinqInternal.Collections
|
||
|
{
|
||
|
internal static partial class Extensions
|
||
|
{
|
||
|
public static ICollection<T> AsCollection<T>(IEnumerable<T> source)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
if (source is string && typeof(T) == typeof(char))
|
||
|
{
|
||
|
return (ICollection<T>)(object)(source as string).ToCharArray();
|
||
|
}
|
||
|
var result = source as ICollection<T>;
|
||
|
return result ?? new ProgressiveCollection<T>(source);
|
||
|
}
|
||
|
|
||
|
public static ICollection<T> AsDistinctCollection<T>(IEnumerable<T> source)
|
||
|
{
|
||
|
// Workaround for .NET 3.5 when all you want is Contains and no duplicates
|
||
|
#if NET35 || !NET_4_6
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
var resultHashSet = source as HashSet<T>;
|
||
|
if (resultHashSet == null)
|
||
|
{
|
||
|
var resultISet = source as ISet<T>;
|
||
|
if (resultISet == null)
|
||
|
{
|
||
|
return new ProgressiveSet<T>(source);
|
||
|
}
|
||
|
return resultISet;
|
||
|
}
|
||
|
return resultHashSet;
|
||
|
#else
|
||
|
return AsSet(source);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public static IList<T> AsList<T>(IEnumerable<T> source)
|
||
|
{
|
||
|
var result = source as IList<T>;
|
||
|
if (result == null)
|
||
|
{
|
||
|
return new ProgressiveList<T>(source);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
public static ISet<T> AsSet<T>(IEnumerable<T> source)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
// Remember that On .NET 3.5 HashSet is not an ISet
|
||
|
var resultISet = source as ISet<T>;
|
||
|
return resultISet ?? new ProgressiveSet<T>(source);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> AsUnaryEnumerable<T>(this T source)
|
||
|
{
|
||
|
yield return source;
|
||
|
}
|
||
|
|
||
|
public static IList<T> AsUnaryList<T>(this T source)
|
||
|
{
|
||
|
return new ProgressiveList<T>
|
||
|
(
|
||
|
AsUnaryEnumerable(source)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static ISet<T> AsUnarySet<T>(this T source)
|
||
|
{
|
||
|
return new ProgressiveSet<T>
|
||
|
(
|
||
|
AsUnaryEnumerable(source)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public static bool HasAtLeast<TSource>(this IEnumerable<TSource> source, int count)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
if (count == 0)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (source is string && typeof(TSource) == typeof(char))
|
||
|
{
|
||
|
return (source as string).Length >= count;
|
||
|
}
|
||
|
var sourceAsCollection = source as ICollection<TSource>;
|
||
|
if (sourceAsCollection != null)
|
||
|
{
|
||
|
return sourceAsCollection.Count >= count;
|
||
|
}
|
||
|
var result = 0;
|
||
|
using (var item = source.GetEnumerator())
|
||
|
{
|
||
|
while (item.MoveNext())
|
||
|
{
|
||
|
checked
|
||
|
{
|
||
|
result++;
|
||
|
}
|
||
|
if (result == count)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> SkipItems<T>(this IEnumerable<T> source, int skipCount)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
return SkipItemsExtracted(source, skipCount);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> SkipItems<T>(this IEnumerable<T> source, Predicate<T> predicateCount, int skipCount)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
return predicateCount == null ? SkipItemsExtracted(source, skipCount) : SkipItemsExtracted(source, predicateCount, skipCount);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> StepItems<T>(this IEnumerable<T> source, int stepCount)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
return StepItemsExtracted(source, stepCount);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> TakeItems<T>(this IEnumerable<T> source, int takeCount)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
return TakeItemsExtracted(source, takeCount);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<T> TakeItems<T>(this IEnumerable<T> source, Predicate<T> predicateCount, int takeCount)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
return predicateCount == null ? TakeItemsExtracted(source, takeCount) : TakeItemsExtracted(source, predicateCount, takeCount);
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<T> SkipItemsExtracted<T>(IEnumerable<T> source, int skipCount)
|
||
|
{
|
||
|
var count = 0;
|
||
|
foreach (var item in source)
|
||
|
{
|
||
|
if (count < skipCount)
|
||
|
{
|
||
|
count++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
yield return item;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<T> SkipItemsExtracted<T>(IEnumerable<T> source, Predicate<T> predicateCount, int skipCount)
|
||
|
{
|
||
|
// NOTICE this method has no null check
|
||
|
var count = 0;
|
||
|
foreach (var item in source)
|
||
|
{
|
||
|
if (count < skipCount)
|
||
|
{
|
||
|
if (predicateCount(item))
|
||
|
{
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
yield return item;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<T> StepItemsExtracted<T>(this IEnumerable<T> source, int stepCount)
|
||
|
{
|
||
|
var count = 0;
|
||
|
foreach (var item in source)
|
||
|
{
|
||
|
if (count % stepCount == 0)
|
||
|
{
|
||
|
count++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
yield return item;
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<T> TakeItemsExtracted<T>(IEnumerable<T> source, int takeCount)
|
||
|
{
|
||
|
var count = 0;
|
||
|
foreach (var item in source)
|
||
|
{
|
||
|
if (count == takeCount)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
yield return item;
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<T> TakeItemsExtracted<T>(IEnumerable<T> source, Predicate<T> predicateCount, int takeCount)
|
||
|
{
|
||
|
// NOTICE this method has no null check
|
||
|
var count = 0;
|
||
|
foreach (var item in source)
|
||
|
{
|
||
|
if (count == takeCount)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
yield return item;
|
||
|
if (predicateCount(item))
|
||
|
{
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|