From d720f413588a37a60c1b9598910bb153f1ded390 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 20 Mar 2020 17:10:51 -0400 Subject: [PATCH] Remove more unnecessary LINQ usage --- .../Collections/CollectionServices.cs | 21 +-------- .../Composition/CompositionResult.cs | 2 +- .../Composition/CompositionResultOfT.cs | 2 +- .../Hosting/AggregateExportProvider.cs | 2 +- .../Composition/Hosting/FilteredCatalog.cs | 2 +- .../Hosting/ImportEngine.PartManager.cs | 2 +- .../src/System/Diagnostics/Process.NonUap.cs | 5 +- .../src/System/Diagnostics/Process.Unix.cs | 20 ++------ .../src/System/Diagnostics/Process.Win32.cs | 46 +++++++++++++------ .../Linq/Expressions/BlockExpression.cs | 2 +- .../Compiler/LambdaCompiler.Statements.cs | 4 +- .../src/System/Net/HeaderInfoTable.cs | 2 +- 12 files changed, 49 insertions(+), 61 deletions(-) diff --git a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Collections/CollectionServices.cs b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Collections/CollectionServices.cs index 6a1af13a3d4ae..a4d632483b084 100644 --- a/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Collections/CollectionServices.cs +++ b/src/libraries/System.ComponentModel.Composition/src/Microsoft/Internal/Collections/CollectionServices.cs @@ -69,12 +69,12 @@ public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable public static IEnumerable? ConcatAllowingNull(this IEnumerable? source, IEnumerable? second) { - if (second == null || !second.FastAny()) + if (second == null || !second.Any()) { return source; } - if (source == null || !source.FastAny()) + if (source == null || !source.Any()) { return second; } @@ -203,23 +203,6 @@ public static EnumerableCardinality GetCardinality(this IEnumerable source } } - public static bool FastAny(this IEnumerable source) - { - // Enumerable.Any underneath doesn't cast to ICollection, - // like it does with many of the other LINQ methods. - // Below is significantly (4x) when mainly working with ICollection - // sources and a little slower if working with mainly IEnumerable - // sources. - - // Cast to ICollection instead of ICollection for performance reasons. - if (source is ICollection collection) - { - return collection.Count > 0; - } - - return source.Any(); - } - public static Stack Copy(this Stack stack) { if (stack == null) diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResult.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResult.cs index 4b4859f1937f9..663372b260a6b 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResult.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResult.cs @@ -26,7 +26,7 @@ public CompositionResult(IEnumerable? errors) public bool Succeeded { - get { return _errors == null || !_errors.FastAny(); } + get { return _errors == null || !_errors.Any(); } } public IEnumerable Errors diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResultOfT.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResultOfT.cs index 12c1339363dec..98a491f8655b2 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResultOfT.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/CompositionResultOfT.cs @@ -37,7 +37,7 @@ internal CompositionResult([AllowNull] T value, IEnumerable? e public bool Succeeded { - get { return _errors == null || !_errors.FastAny(); } + get { return _errors == null || !_errors.Any(); } } public IEnumerable Errors diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AggregateExportProvider.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AggregateExportProvider.cs index 84a4e48b75dcd..9250e961413bd 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AggregateExportProvider.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/AggregateExportProvider.cs @@ -179,7 +179,7 @@ protected override IEnumerable GetExportsCore(ImportDefinition definitio { bool cardinalityCheckResult = provider.TryGetExports(definition, atomicComposition, out IEnumerable? exports); Debug.Assert(exports != null); - bool anyExports = exports.FastAny(); + bool anyExports = exports.Any(); if (cardinalityCheckResult && anyExports) { // NOTE : if the provider returned nothing, we need to proceed, even if it indicated that the diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/FilteredCatalog.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/FilteredCatalog.cs index 6b39064e59dc0..2c7ba12c76f1d 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/FilteredCatalog.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/FilteredCatalog.cs @@ -230,7 +230,7 @@ private void OnChangingInternal(object? sender, ComposablePartCatalogChangeEvent e.AtomicComposition); // Only fire if we need to - if (result.AddedDefinitions.FastAny() || result.RemovedDefinitions.FastAny()) + if (result.AddedDefinitions.Any() || result.RemovedDefinitions.Any()) { return result; } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ImportEngine.PartManager.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ImportEngine.PartManager.cs index 9adc214c1c2ab..08e34eca55516 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ImportEngine.PartManager.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/Hosting/ImportEngine.PartManager.cs @@ -174,7 +174,7 @@ public void UpdateDisposableDependencies(ImportDefinition import, Export[] expor if (disposableExports == null) { _importedDisposableExports.Remove(import); - if (!_importedDisposableExports.FastAny()) + if (!_importedDisposableExports.Any()) { _importedDisposableExports = null; } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs index 20cf872e87c70..d838c14071fab 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.ComponentModel; -using System.Linq; namespace System.Diagnostics { @@ -23,9 +22,9 @@ public void Kill(bool entireProcessTree) if (IsSelfOrDescendantOf(GetCurrentProcess())) throw new InvalidOperationException(SR.KillEntireProcessTree_DisallowedBecauseTreeContainsCallingProcess); - IEnumerable result = KillTree(); + List? result = KillTree(); - if (result.Any()) + if (result != null && result.Count != 0) throw new AggregateException(SR.KillEntireProcessTree_TerminationIncomplete, result); } } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs index 889f06ad25651..129963c07793c 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs @@ -5,10 +5,7 @@ using Microsoft.Win32.SafeHandles; using System.Collections.Generic; using System.ComponentModel; -using System.Globalization; using System.IO; -using System.Linq; -using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; @@ -86,11 +83,11 @@ public void Kill() private bool GetHasExited(bool refresh) => GetWaitState().GetExited(out _, refresh); - private IEnumerable KillTree() + private List? KillTree() { List? exceptions = null; KillTree(ref exceptions); - return exceptions ?? Enumerable.Empty(); + return exceptions; } private void KillTree(ref List? exceptions) @@ -111,7 +108,7 @@ private void KillTree(ref List? exceptions) // Ignore 'process no longer exists' error. if (error != Interop.Error.ESRCH) { - AddException(ref exceptions, new Win32Exception()); + (exceptions ??= new List()).Add(new Win32Exception()); } return; } @@ -125,7 +122,7 @@ private void KillTree(ref List? exceptions) // Ignore 'process no longer exists' error. if (error != Interop.Error.ESRCH) { - AddException(ref exceptions, new Win32Exception()); + (exceptions ??= new List()).Add(new Win32Exception()); } } @@ -134,15 +131,6 @@ private void KillTree(ref List? exceptions) childProcess.KillTree(ref exceptions); childProcess.Dispose(); } - - void AddException(ref List? list, Exception e) - { - if (list == null) - { - list = new List(); - } - list.Add(e); - } } /// Discards any information about the associated process. diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs index 565b02ea19e05..5ed1aa25d26a8 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; @@ -365,7 +364,7 @@ private unsafe int ParentProcessId Id == process.Id && StartTime == process.StartTime; - private IEnumerable KillTree() + private List? KillTree() { // The process's structures will be preserved as long as a handle is held pointing to them, even if the process exits or // is terminated. A handle is held here to ensure a stable reference to the process during execution. @@ -373,17 +372,17 @@ private IEnumerable KillTree() { // If the process has exited, the handle is invalid. if (handle.IsInvalid) - return Enumerable.Empty(); + return null; return KillTree(handle); } } - private IEnumerable KillTree(SafeProcessHandle handle) + private List? KillTree(SafeProcessHandle handle) { Debug.Assert(!handle.IsInvalid); - List exceptions = new List(); + List? exceptions = null; try { @@ -394,16 +393,19 @@ private IEnumerable KillTree(SafeProcessHandle handle) } catch (Win32Exception e) { - exceptions.Add(e); + (exceptions ??= new List()).Add(e); } - IReadOnlyList<(Process Process, SafeProcessHandle Handle)> children = GetProcessHandlePairs(p => SafePredicateTest(() => IsParentOf(p))); + List<(Process Process, SafeProcessHandle Handle)> children = GetProcessHandlePairs(p => SafePredicateTest(() => IsParentOf(p))); try { foreach ((Process Process, SafeProcessHandle Handle) child in children) { - IEnumerable exceptionsFromChild = child.Process.KillTree(child.Handle); - exceptions.AddRange(exceptionsFromChild); + List? exceptionsFromChild = child.Process.KillTree(child.Handle); + if (exceptionsFromChild != null) + { + (exceptions ??= new List()).AddRange(exceptionsFromChild); + } } } finally @@ -418,12 +420,28 @@ private IEnumerable KillTree(SafeProcessHandle handle) return exceptions; } - private IReadOnlyList<(Process Process, SafeProcessHandle Handle)> GetProcessHandlePairs(Func predicate) + private List<(Process Process, SafeProcessHandle Handle)> GetProcessHandlePairs(Func predicate) { - return GetProcesses() - .Select(p => (Process: p, Handle: SafeGetHandle(p))) - .Where(p => !p.Handle.IsInvalid && predicate(p.Process)) - .ToList(); + var results = new List<(Process Process, SafeProcessHandle Handle)>(); + + foreach (Process p in GetProcesses()) + { + SafeProcessHandle h = SafeGetHandle(p); + if (!h.IsInvalid) + { + if (predicate(p)) + { + results.Add((p, h)); + } + else + { + p.Dispose(); + h.Dispose(); + } + } + } + + return results; static SafeProcessHandle SafeGetHandle(Process process) { diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/BlockExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/BlockExpression.cs index ff2a2efdd0513..d2658af686e40 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/BlockExpression.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/BlockExpression.cs @@ -1040,7 +1040,7 @@ private static BlockExpression BlockCore(Type? type, ReadOnlyCollection> buckets, // explicit guard Label secondHalf = _ilg.DefineLabel(); _ilg.Emit(OpCodes.Ldloc, info.Value); - EmitConstant(buckets[mid - 1].Last().Constant); + EmitConstant(buckets[mid - 1][^1].Constant); _ilg.Emit(info.IsUnsigned ? OpCodes.Bgt_Un : OpCodes.Bgt, secondHalf); EmitSwitchBuckets(info, buckets, first, mid - 1); _ilg.MarkLabel(secondHalf); @@ -582,7 +582,7 @@ private void EmitSwitchBucket(SwitchInfo info, List bucket) { after = _ilg.DefineLabel(); _ilg.Emit(OpCodes.Ldloc, info.Value); - EmitConstant(bucket.Last().Constant); + EmitConstant(bucket[^1].Constant); _ilg.Emit(info.IsUnsigned ? OpCodes.Bgt_Un : OpCodes.Bgt, after.Value); _ilg.Emit(OpCodes.Ldloc, info.Value); EmitConstant(bucket[0].Constant); diff --git a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/HeaderInfoTable.cs b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/HeaderInfoTable.cs index d261a94efcdf3..8b6a13df26c8b 100644 --- a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/HeaderInfoTable.cs +++ b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/HeaderInfoTable.cs @@ -67,7 +67,7 @@ private static bool IsDuringExpiresAttributeParsing(string singleValue) // Current cookie doesn't contain any attributes. if (!singleValue.Contains(';')) return false; - string lastElement = singleValue.Split(';').Last(); + string lastElement = singleValue.Split(';')[^1]; bool noComma = !lastElement.Contains(','); string lastAttribute = lastElement.Split('=')[0].Trim();