diff --git a/SharedCode.Core/Linq/CollectionExtensions.cs b/SharedCode.Core/Linq/CollectionExtensions.cs index c09ee5b..0c7524c 100644 --- a/SharedCode.Core/Linq/CollectionExtensions.cs +++ b/SharedCode.Core/Linq/CollectionExtensions.cs @@ -70,9 +70,12 @@ public static TCollection AddRangeIfRangeNotNull(this TCollectio _ = @this ?? throw new ArgumentNullException(nameof(@this)); _ = predicate ?? throw new ArgumentNullException(nameof(predicate)); - foreach (var item in @this.Where(item => predicate(item))) + foreach (var item in @this) { - return item; + if (predicate(item)) + { + return item; + } } return default; @@ -92,9 +95,12 @@ public static Collection FindAll(this ICollection @this, Predicate p _ = predicate ?? throw new ArgumentNullException(nameof(predicate)); var all = new Collection(); - foreach (var item in @this.Where(item => predicate(item))) + foreach (var item in @this) { - all.Add(item); + if (predicate(item)) + { + all.Add(item); + } } return all; @@ -175,7 +181,7 @@ public static int FindIndex( throw new ArgumentOutOfRangeException(nameof(@this)); } - if (predicate(@this.ElementAt(i))) + if (predicate(@this is IList list ? list[i] : @this.ElementAt(i))) { return i; } @@ -199,9 +205,10 @@ public static int FindIndex( for (var i = @this.Count - 1; i >= 0; i--) { - if (predicate(@this.ElementAt(i))) + var item = @this is IList list ? list[i] : @this.ElementAt(i); + if (predicate(item)) { - return @this.ElementAt(i); + return item; } } @@ -285,7 +292,7 @@ public static int FindLastIndex( throw new ArgumentOutOfRangeException(nameof(@this)); } - if (predicate(@this.ElementAt(i))) + if (predicate(@this is IList list ? list[i] : @this.ElementAt(i))) { return i; } @@ -360,12 +367,27 @@ public static int RemoveAll(this ICollection @this, Predicate match) var count = 0; for (var i = 0; i < @this.Count; i++) { - if (!match(@this.ElementAt(i))) + if (@this is IList list) { - continue; + var item = list[i]; + if (!match(item)) + { + continue; + } + + list.RemoveAt(i); + } + else + { + var item = @this.ElementAt(i); + if (!match(item)) + { + continue; + } + + _ = @this.Remove(item); } - _ = @this.Remove(@this.ElementAt(i)); count++; i--; } diff --git a/SharedCode.Core/Linq/EnumerableExtensions.cs b/SharedCode.Core/Linq/EnumerableExtensions.cs index b5c1137..9819bad 100644 --- a/SharedCode.Core/Linq/EnumerableExtensions.cs +++ b/SharedCode.Core/Linq/EnumerableExtensions.cs @@ -34,8 +34,43 @@ public static class EnumerableExtensions /// The default value. /// The aggregate function. /// The result. - public static T? Aggregate(this IEnumerable @this, T? defaultValue, Func aggregateFunction) => - @this?.Any() ?? false ? System.Linq.Enumerable.Aggregate(@this, (a, b) => aggregateFunction(a, b)!) : defaultValue; + public static T? Aggregate(this IEnumerable @this, T? defaultValue, Func aggregateFunction) + { + _ = aggregateFunction ?? throw new ArgumentNullException(nameof(aggregateFunction)); + + if (@this is null) + { + return defaultValue; + } + + if (@this is ICollection collection) + { + return collection.Count == 0 + ? defaultValue + : System.Linq.Enumerable.Aggregate(@this, (a, b) => aggregateFunction(a, b)!); + } + + if (@this is IReadOnlyCollection readOnlyCollection) + { + return readOnlyCollection.Count == 0 + ? defaultValue + : System.Linq.Enumerable.Aggregate(@this, (a, b) => aggregateFunction(a, b)!); + } + + using var enumerator = @this.GetEnumerator(); + if (!enumerator.MoveNext()) + { + return defaultValue; + } + + T? result = enumerator.Current; + while (enumerator.MoveNext()) + { + result = aggregateFunction(result, enumerator.Current); + } + + return result; + } /// /// Starts execution of IQueryable on a ThreadPool thread and returns immediately with a @@ -236,7 +271,8 @@ public static int IndexOf(this IEnumerable @this, TSource valu /// /// true if the source enumerable is not null and contains items; otherwise, false. /// - public static bool IsNotNullOrEmpty(this IEnumerable @this) => @this?.Any() == true; + public static bool IsNotNullOrEmpty(this IEnumerable @this) => + @this is not null && (@this.TryGetNonEnumeratedCount(out var count) ? count > 0 : @this.Any()); /// /// Determines whether the source enumerable is null or contains no items. @@ -260,7 +296,7 @@ public static int IndexOf(this IEnumerable @this, TSource valu public static IEnumerable OrderBy(this IEnumerable @this, string sortExpression) { sortExpression += string.Empty; - var parts = sortExpression.Split(' '); + var parts = sortExpression.Split(' ', StringSplitOptions.RemoveEmptyEntries); var descending = false; if (parts.Length == 0 || string.IsNullOrEmpty(parts[0])) diff --git a/SharedCode.Core/Reflection/DeepCloneGenerator.cs b/SharedCode.Core/Reflection/DeepCloneGenerator.cs index aa6e18f..16b60d5 100644 --- a/SharedCode.Core/Reflection/DeepCloneGenerator.cs +++ b/SharedCode.Core/Reflection/DeepCloneGenerator.cs @@ -211,10 +211,15 @@ internal static T[] Clone1DimArraySafeInternal(T[] obj, DeepCloneState state) var rank = obj.Rank; - var lengths = Enumerable.Range(0, rank).Select(obj.GetLength).ToArray(); - - var lowerBounds = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray(); - var idxes = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray(); + var lengths = new int[rank]; + var lowerBounds = new int[rank]; + var idxes = new int[rank]; + for (var i = 0; i < rank; i++) + { + lengths[i] = obj.GetLength(i); + lowerBounds[i] = obj.GetLowerBound(i); + idxes[i] = lowerBounds[i]; + } var elementType = obj.GetType().GetElementType(); var outArray = Array.CreateInstance(elementType!, lengths, lowerBounds); diff --git a/SharedCode.DependencyInjection/TypeSourceSelector.cs b/SharedCode.DependencyInjection/TypeSourceSelector.cs index 297029f..25c6001 100644 --- a/SharedCode.DependencyInjection/TypeSourceSelector.cs +++ b/SharedCode.DependencyInjection/TypeSourceSelector.cs @@ -154,11 +154,12 @@ public ICatalogSelector FromAssemblyDependencies(Assembly assembly) } #endif - var assemblies = new List { assembly }; + var referencedAssemblies = assembly.GetReferencedAssemblies(); + var assemblies = new List(capacity: referencedAssemblies.Length + 1) { assembly }; try { - foreach (var dependencyName in assembly.GetReferencedAssemblies()) + foreach (var dependencyName in referencedAssemblies) { try {