@@ -313,19 +313,35 @@ public static void ForEach<T>(this ISynchronizedCollection<T> target, Cancellati
313313 } ) ;
314314 }
315315
316- public static IEnumerable < T > Shuffle < T > ( this IEnumerable < T > target )
316+ /// <summary>
317+ /// Randomizes the order of the source.
318+ /// </summary>
319+ public static IEnumerable < T > Shuffle < T > (
320+ this IEnumerable < T > target , Random ? rnd = null )
317321 {
318322 if ( target is null )
319323 throw new ArgumentNullException ( nameof ( target ) ) ;
320324 Contract . EndContractBlock ( ) ;
321325
322- var r = new Random ( ) ;
326+ var r = rnd ?? new Random ( ) ;
323327 return target . OrderBy ( _ => r . Next ( ) ) ;
324328 }
325329
326- // Ensures an optimized means of acquiring Any();
327- public static bool HasAny < T > ( this IEnumerable < T > source ) => source . HasAtLeast ( 1 ) ;
330+ /// <summary>
331+ /// Tests the count of the source to see if there's any items.
332+ /// </summary>
333+ /// <exception cref="ArgumentNullException">If the <paramref name="source"/> is null.</exception>
334+ /// <remarks>
335+ /// First checks the type to see if a count can be aquired directly. If not, it will iterate through the source to count the items.
336+ /// </remarks>
337+ public static bool HasAny < T > ( this IEnumerable < T > source )
338+ => source . HasAtLeast ( 1 ) ;
328339
340+ /// <summary>
341+ /// Tests the count of the source to see if there's at least the <paramref name="minimum"/> number of items.
342+ /// </summary>
343+ /// <exception cref="ArgumentOutOfRangeException">If the <paramref name="minimum"/> is less than 1.</exception>
344+ /// <inheritdoc cref="HasAny{T}(IEnumerable{T})"/>
329345 public static bool HasAtLeast < T > ( this IEnumerable < T > source , int minimum )
330346 {
331347 if ( source is null )
@@ -338,8 +354,12 @@ public static bool HasAtLeast<T>(this IEnumerable<T> source, int minimum)
338354 {
339355 case T [ ] array :
340356 return array . Length >= minimum ;
357+ case IReadOnlyCollection < T > collection :
358+ return collection . Count >= minimum ;
341359 case ICollection collection :
342360 return collection . Count >= minimum ;
361+ case ICollection < T > collection :
362+ return collection . Count >= minimum ;
343363 }
344364
345365 using IEnumerator < T > ? e = source . GetEnumerator ( ) ;
@@ -351,6 +371,9 @@ public static bool HasAtLeast<T>(this IEnumerable<T> source, int minimum)
351371 return false ;
352372 }
353373
374+ /// <summary>
375+ /// Synchronizes enumerting by locking on the enumerator.
376+ /// </summary>
354377 public static bool ConcurrentTryMoveNext < T > ( this IEnumerator < T > source , out T item )
355378 {
356379 // Always lock on next to prevent concurrency issues.
@@ -362,10 +385,14 @@ public static bool ConcurrentTryMoveNext<T>(this IEnumerator<T> source, out T it
362385 return true ;
363386 }
364387 }
388+
365389 item = default ! ;
366390 return false ;
367391 }
368392
393+ /// <summary>
394+ /// Syncronizes enumerting by locking on the enumerator and invokes the provided handlers depending on if .MoveNext() was true.
395+ /// </summary>
369396 public static bool ConcurrentMoveNext < T > ( this IEnumerator < T > source , Action < T > trueHandler , Action ? falseHandler = null )
370397 {
371398 // Always lock on next to prevent concurrency issues.
@@ -477,86 +504,19 @@ public static string ToConcatenatedString<T>(this IEnumerable<T> source, Func<T,
477504 return b . ToString ( ) ;
478505 }
479506
480- /// <summary>
481- /// Shortcut to String.Join() using "," as a default value.
482- /// </summary>
483- public static string Join ( this string [ ] array , char separator )
484- {
485- if ( array is null )
486- throw new ArgumentNullException ( nameof ( array ) ) ;
487- Contract . EndContractBlock ( ) ;
488-
489- return string . Join ( separator + string . Empty , array ) ;
490- }
491-
492- public static string Join ( this string [ ] array , string separator = "," )
493- {
494- if ( array is null )
495- throw new ArgumentNullException ( nameof ( array ) ) ;
496- if ( separator is null )
497- throw new ArgumentNullException ( nameof ( separator ) ) ;
498- Contract . EndContractBlock ( ) ;
499-
500- return string . Join ( separator , array ) ;
501- }
502-
503- /// <summary>
504- /// Concatenates a set of values into a single string using a character as a separator.
505- /// </summary>
506- public static string JoinToString < T > ( this IEnumerable < T > source , char separator )
507- {
508- if ( source is null ) throw new ArgumentNullException ( nameof ( source ) ) ;
509- Contract . EndContractBlock ( ) ;
510-
511- var sb = new StringBuilder ( ) ;
512- using ( IEnumerator < T > ? enumerator = source . GetEnumerator ( ) )
513- {
514- if ( enumerator . MoveNext ( ) )
515- sb . Append ( enumerator . Current ) ;
516- while ( enumerator . MoveNext ( ) )
517- sb . Append ( separator ) . Append ( enumerator . Current ) ;
518- }
519-
520- return sb . ToString ( ) ;
521- }
522-
523- /// <summary>
524- /// Concatenates set of values into a single string using another string as a separator.
525- /// </summary>
526- public static string JoinToString < T > ( this IEnumerable < T > source , string separator )
527- {
528- if ( source is null ) throw new ArgumentNullException ( nameof ( source ) ) ;
529- if ( separator is null ) throw new ArgumentNullException ( nameof ( separator ) ) ;
530- Contract . EndContractBlock ( ) ;
531-
532- var sb = new StringBuilder ( ) ;
533- using ( IEnumerator < T > ? enumerator = source . GetEnumerator ( ) )
534- {
535- if ( enumerator . MoveNext ( ) )
536- sb . Append ( enumerator . Current ) ;
537- while ( enumerator . MoveNext ( ) )
538- sb . Append ( separator ) . Append ( enumerator . Current ) ;
539- }
540-
541- return sb . ToString ( ) ;
542- }
543-
544507 /*public static T ValidateNotNull<T>(this T target)
545508 {
546509
547510 Contract.Assume(target is not null);
548511 return target;
549512 }*/
550513
551- public static Dictionary < TKey , TValue > ToDictionary < TKey , TValue > ( this ParallelQuery < KeyValuePair < TKey , TValue > > source )
552- where TKey : notnull
553- {
554- if ( source is null ) throw new ArgumentNullException ( nameof ( source ) ) ;
555- Contract . EndContractBlock ( ) ;
556-
557- return source . ToDictionary ( kvp => kvp . Key , kvp => kvp . Value ) ;
558- }
559-
514+ #if NET9_0_OR_GREATER
515+ #else
516+ /// <summary>
517+ /// Returns a dictionary from the source key-value pairs.
518+ /// </summary>
519+ /// <exception cref="ArgumentNullException">If the <paramref name="source"/> is null.</exception>
560520 public static Dictionary < TKey , TValue > ToDictionary < TKey , TValue > ( this IEnumerable < KeyValuePair < TKey , TValue > > source )
561521 where TKey : notnull
562522 {
@@ -565,7 +525,12 @@ public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this IEnumerab
565525
566526 return source . ToDictionary ( kvp => kvp . Key , kvp => kvp . Value ) ;
567527 }
528+ #endif
568529
530+ /// <summary>
531+ /// Converts an enumerable to a sorted dictionary.
532+ /// </summary>
533+ /// <exception cref="ArgumentNullException">If the <paramref name="source"/> is null.</exception>
569534 public static SortedDictionary < TKey , TValue > ToSortedDictionary < TKey , TValue > ( this IEnumerable < KeyValuePair < TKey , TValue > > source )
570535 where TKey : notnull
571536 {
@@ -579,6 +544,10 @@ public static SortedDictionary<TKey, TValue> ToSortedDictionary<TKey, TValue>(th
579544 return result ;
580545 }
581546
547+ /// <summary>
548+ /// Converts an enumerable to a sorted dictionary.
549+ /// </summary>
550+ /// <exception cref="ArgumentNullException">If the <paramref name="source"/>, <paramref name="keySelector"/>, or <typeparamref name="TValue"/> are null.</exception>
582551 public static SortedDictionary < TKey , TValue > ToSortedDictionary < TSource , TKey , TValue > ( this IEnumerable < TSource > source ,
583552 Func < TSource , TKey > keySelector , Func < TSource , TValue > valueSelector )
584553 where TKey : notnull
@@ -595,6 +564,10 @@ public static SortedDictionary<TKey, TValue> ToSortedDictionary<TSource, TKey, T
595564 return result ;
596565 }
597566
567+ /// <summary>
568+ /// Converts a grouping to a sorted dictionary.
569+ /// </summary>
570+ /// <exception cref="ArgumentNullException">If the <paramref name="source"/> is null.</exception>
598571 public static SortedDictionary < TKey , IEnumerable < TValue > > ToSortedDictionary < TKey , TValue > ( this IEnumerable < IGrouping < TKey , TValue > > source )
599572 where TKey : notnull
600573 {
@@ -664,18 +637,8 @@ public static bool IsEquivalentTo<T>(this IEnumerable<T> source, IEnumerable<T>
664637 if ( source is null || target is null )
665638 return false ;
666639
667- if ( source is IReadOnlyCollection < T > sC && target is IReadOnlyCollection < T > tC && sC . Count != tC . Count )
668- return false ;
669-
670- using IEnumerator < T > ? enumSource = source . GetEnumerator ( ) ;
671- using IEnumerator < T > ? enumTarget = target . GetEnumerator ( ) ;
672- while ( enumSource . MoveNext ( ) && enumTarget . MoveNext ( ) )
673- {
674- if ( ! enumSource . Current . Equals ( enumTarget . Current ) )
675- return false ;
676- }
677-
678- return true ;
640+ // Both are not null, okay go.
641+ return source . SequenceEqual ( target ) ;
679642 }
680643
681644 /// <summary>
@@ -843,6 +806,9 @@ private class OrderByInfo
843806 }
844807 #endregion
845808
809+ /// <summary>
810+ /// A nullable struct version of FirstOrDefault.
811+ /// </summary>
846812 public static T ? NullableFirstOrDefault < T > ( this IEnumerable < T > source )
847813 where T : struct
848814 {
@@ -854,6 +820,9 @@ private class OrderByInfo
854820 return null ;
855821 }
856822
823+ /// <summary>
824+ /// Rotates through each enumerable and returns the next value until none are left.
825+ /// </summary>
857826 public static IEnumerable < T > Weave < T > ( this IEnumerable < IEnumerable < T > > source )
858827 {
859828 LinkedList < IEnumerator < T > > ? queue = null ;
@@ -1067,6 +1036,9 @@ public static IEnumerator<T> Preflight<T>(
10671036 yield return source . Current ;
10681037 }
10691038
1039+ /// <summary>
1040+ /// Executes an action when the begins <paramref name="source"/> enumeration.
1041+ /// </summary>
10701042 public static IEnumerable < T > BeforeGetEnumerator < T > (
10711043 this IEnumerable < T > source ,
10721044 Action before )
0 commit comments