diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index bd3134aa1c1752..adda9e7ca4f3f9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -18,7 +18,7 @@ internal static IList GetCustomAttributesInternal(RuntimeTy Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } @@ -28,7 +28,7 @@ internal static IList GetCustomAttributesInternal(RuntimeFi Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } @@ -38,7 +38,7 @@ internal static IList GetCustomAttributesInternal(RuntimeMe Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } @@ -87,13 +87,13 @@ internal static IList GetCustomAttributesInternal(RuntimePa { Debug.Assert(target is not null); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; IList cad = GetCustomAttributes(target.GetRuntimeModule()!, target.MetadataToken); PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } - private static ReadOnlyCollection GetCombinedList(IList customAttributes, ref RuntimeType.ListBuilder pseudoAttributes) + private static ReadOnlyCollection GetCombinedList(IList customAttributes, ref ListBuilder pseudoAttributes) { Debug.Assert(pseudoAttributes.Count != 0); @@ -922,7 +922,7 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp if (type.IsGenericType && !type.IsGenericTypeDefinition) type = (type.GetGenericTypeDefinition() as RuntimeType)!; - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(type, caType, ref pcas); // if we are asked to go up the hierarchy chain we have to do it now and regardless of the @@ -935,7 +935,7 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp return attributes; } - RuntimeType.ListBuilder result = default; + ListBuilder result = default; bool mustBeInheritable = false; for (int i = 0; i < pcas.Count; i++) @@ -964,7 +964,7 @@ internal static object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeTy if (method.IsGenericMethod && !method.IsGenericMethodDefinition) method = (method.GetGenericMethodDefinition() as RuntimeMethodInfo)!; - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(method, caType, ref pcas); // if we are asked to go up the hierarchy chain we have to do it now and regardless of the @@ -977,7 +977,7 @@ internal static object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeTy return attributes; } - RuntimeType.ListBuilder result = default; + ListBuilder result = default; bool mustBeInheritable = false; for (int i = 0; i < pcas.Count; i++) @@ -1033,7 +1033,7 @@ internal static object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType Debug.Assert(field is not null); Debug.Assert(caType is not null); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(field, caType, ref pcas); object[] attributes = GetCustomAttributes(field.GetRuntimeModule(), field.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); @@ -1045,7 +1045,7 @@ internal static object[] GetCustomAttributes(RuntimeParameterInfo parameter, Run Debug.Assert(parameter is not null); Debug.Assert(caType is not null); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(parameter, caType, ref pcas); object[] attributes = GetCustomAttributes(parameter.GetRuntimeModule()!, parameter.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); @@ -1101,7 +1101,7 @@ private static bool IsCustomAttributeDefined( { Debug.Assert(attributeCtorToken == 0); - RuntimeType.ListBuilder derivedAttributes = default; + ListBuilder derivedAttributes = default; for (int i = 0; i < attributeTokens.Length; i++) { @@ -1139,7 +1139,7 @@ private static bool IsCustomAttributeDefined( private static object[] GetCustomAttributes( RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType) { - RuntimeType.ListBuilder attributes = default; + ListBuilder attributes = default; AddCustomAttributes(ref attributes, decoratedModule, decoratedMetadataToken, attributeFilterType, false, default); @@ -1156,11 +1156,11 @@ private static object[] GetCustomAttributes( "attribute instantiation which is present in the code linker has analyzed." + "As such the reflection usage in this method will never fail as those methods/fields will be present.")] private static void AddCustomAttributes( - ref RuntimeType.ListBuilder attributes, + ref ListBuilder attributes, RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType? attributeFilterType, bool mustBeInheritable, // The derivedAttributes list must be passed by value so that it is not modified with the discovered attributes - RuntimeType.ListBuilder derivedAttributes) + ListBuilder derivedAttributes) { CustomAttributeRecord[] car = RuntimeCustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken); @@ -1295,7 +1295,7 @@ private static bool FilterCustomAttributeRecord( MetadataToken decoratedToken, RuntimeType attributeFilterType, bool mustBeInheritable, - ref RuntimeType.ListBuilder derivedAttributes, + ref ListBuilder derivedAttributes, out RuntimeType attributeType, out IRuntimeMethodInfo? ctorWithParameters, out bool isVarArg) @@ -1409,7 +1409,7 @@ private static bool MatchesTypeFilter(RuntimeType attributeType, RuntimeType att #region Private Static Methods private static bool AttributeUsageCheck( - RuntimeType attributeType, bool mustBeInheritable, ref RuntimeType.ListBuilder derivedAttributes) + RuntimeType attributeType, bool mustBeInheritable, ref ListBuilder derivedAttributes) { AttributeUsageAttribute? attributeUsageAttribute = null; @@ -1595,7 +1595,7 @@ private static void VerifyPseudoCustomAttribute(RuntimeType pca) #endregion #region Internal Static - internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(type is not null); Debug.Assert(caType is not null); @@ -1639,7 +1639,7 @@ internal static bool IsDefined(RuntimeType type, RuntimeType? caType) return false; } - internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(method is not null); Debug.Assert(caType is not null); @@ -1679,7 +1679,7 @@ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType? caType) return false; } - internal static void GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(parameter is not null); Debug.Assert(caType is not null); @@ -1735,7 +1735,7 @@ internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType? caTy return false; } - internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(field is not null); Debug.Assert(caType is not null); diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index e9fddd436b3d34..a76d750184af87 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -53,87 +53,6 @@ internal enum MemberListType HandleToInfo } - // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element. - internal struct ListBuilder where T : class - { - private T[]? _items; - private T _item; - private int _count; - private int _capacity; - - public ListBuilder(int capacity) - { - _items = null; - _item = null!; - _count = 0; - _capacity = capacity; - } - - public T this[int index] - { - get - { - Debug.Assert(index < Count); - return (_items != null) ? _items[index] : _item; - } - } - - public T[] ToArray() - { - if (_count == 0) - return Array.Empty(); - if (_count == 1) - return new T[1] { _item }; - - Array.Resize(ref _items, _count); - _capacity = _count; - return _items!; - } - - public void CopyTo(object[] array, int index) - { - if (_count == 0) - return; - - if (_count == 1) - { - array[index] = _item; - return; - } - - Array.Copy(_items!, 0, array, index, _count); - } - - public int Count => _count; - - public void Add(T item) - { - if (_count == 0) - { - _item = item; - } - else - { - if (_count == 1) - { - if (_capacity < 2) - _capacity = 4; - _items = new T[_capacity]; - _items[0] = _item; - } - else if (_capacity == _count) - { - int newCapacity = 2 * _capacity; - Array.Resize(ref _items, newCapacity); - _capacity = newCapacity; - } - - _items![_count] = item; - } - _count++; - } - } - internal sealed class RuntimeTypeCache { private const int MAXNAMELEN = 1024; @@ -2826,7 +2745,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn } // All the methods have the exact same name and sig so return the most derived one. - return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo; + return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.AsSpan()); } } @@ -2855,7 +2774,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn } if ((bindingAttr & BindingFlags.ExactBinding) != 0) - return System.DefaultBinder.ExactBinding(candidates.ToArray(), types) as ConstructorInfo; + return System.DefaultBinder.ExactBinding(candidates.AsSpan(), types); binder ??= DefaultBinder; return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as ConstructorInfo; @@ -2893,7 +2812,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn } if ((bindingAttr & BindingFlags.ExactBinding) != 0) - return System.DefaultBinder.ExactPropertyBinding(candidates.ToArray(), returnType, types); + return System.DefaultBinder.ExactPropertyBinding(candidates.AsSpan(), returnType, types); binder ??= DefaultBinder; return binder.SelectProperty(bindingAttr, candidates.ToArray(), returnType, types, modifiers); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 8f45dd1a4d5b92..b55bda48bb1e22 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -416,7 +416,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs index bee3e2f9d1aad5..4725a332e17b03 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs @@ -38,7 +38,7 @@ protected sealed override ConstructorInfo GetConstructorImpl(BindingFlags bindin } if ((bindingAttr & BindingFlags.ExactBinding) != 0) - return System.DefaultBinder.ExactBinding(candidates.ToArray(), types) as ConstructorInfo; + return System.DefaultBinder.ExactBinding(candidates.AsSpan(), types); binder ??= DefaultBinder; diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 2b774a2f4fd550..32761e742f1726 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -707,6 +707,7 @@ + @@ -2719,4 +2720,4 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs index 3adad0979c6ebf..c60123dc1e2f32 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs @@ -3,9 +3,10 @@ #pragma warning disable CA1852 // DefaultBinder is derived from in some targets -using System.Reflection; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Runtime.InteropServices; using CultureInfo = System.Globalization.CultureInfo; @@ -788,12 +789,10 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat // Return any exact bindings that may exist. (This method is not defined on the // Binder and is used by RuntimeType.) - public static MethodBase? ExactBinding(MethodBase[] match, Type[] types) + public static T? ExactBinding(ReadOnlySpan match, Type[] types) where T : MethodBase { - ArgumentNullException.ThrowIfNull(match); - - MethodBase[] aExactMatches = new MethodBase[match.Length]; - int cExactMatches = 0; + T singleMatch = default!; + using ValueListBuilder exactMatches = new(new Span(ref singleMatch)); for (int i = 0; i < match.Length; i++) { @@ -802,6 +801,7 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat { continue; } + int j; for (j = 0; j < types.Length; j++) { @@ -811,29 +811,27 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat if (!pCls.Equals(types[j])) break; } + if (j < types.Length) continue; // Add the exact match to the array of exact matches. - aExactMatches[cExactMatches] = match[i]; - cExactMatches++; + exactMatches.Append(match[i]); } - if (cExactMatches == 0) + if (exactMatches.Length == 0) return null; - if (cExactMatches == 1) - return aExactMatches[0]; + if (exactMatches.Length == 1) + return exactMatches[0]; - return FindMostDerivedNewSlotMeth(aExactMatches, cExactMatches); + return FindMostDerivedNewSlotMeth(exactMatches.AsSpan()); } // Return any exact bindings that may exist. (This method is not defined on the // Binder and is used by RuntimeType.) - public static PropertyInfo? ExactPropertyBinding(PropertyInfo[] match, Type? returnType, Type[]? types) + public static PropertyInfo? ExactPropertyBinding(ReadOnlySpan match, Type? returnType, Type[]? types) { - ArgumentNullException.ThrowIfNull(match); - PropertyInfo? bestMatch = null; int typesLength = (types != null) ? types.Length : 0; for (int i = 0; i < match.Length; i++) @@ -1126,12 +1124,12 @@ private static int GetHierarchyDepth(Type t) return depth; } - internal static MethodBase? FindMostDerivedNewSlotMeth(MethodBase[] match, int cMatches) + internal static T? FindMostDerivedNewSlotMeth(ReadOnlySpan match) where T : MethodBase { int deepestHierarchy = 0; - MethodBase? methWithDeepestHierarchy = null; + T? methodWithDeepestHierarchy = null; - for (int i = 0; i < cMatches; i++) + for (int i = 0; i < match.Length; i++) { // Calculate the depth of the hierarchy of the declaring type of the // current method. @@ -1141,18 +1139,18 @@ private static int GetHierarchyDepth(Type t) // This can only happen if at least one is vararg or generic. if (currentHierarchyDepth == deepestHierarchy) { - throw ThrowHelper.GetAmbiguousMatchException(methWithDeepestHierarchy!); + throw ThrowHelper.GetAmbiguousMatchException(methodWithDeepestHierarchy!); } // Check to see if this method is on the most derived class. if (currentHierarchyDepth > deepestHierarchy) { deepestHierarchy = currentHierarchyDepth; - methWithDeepestHierarchy = match[i]; + methodWithDeepestHierarchy = match[i]; } } - return methWithDeepestHierarchy; + return methodWithDeepestHierarchy; } // This method will sort the vars array into the mapping order stored diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ListBuilder.cs similarity index 58% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs rename to src/libraries/System.Private.CoreLib/src/System/Reflection/ListBuilder.cs index 12ccb40f48aa27..5b8dd54ff92f06 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/ListBuilder.cs @@ -2,23 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; -namespace System.Reflection.Runtime.General +namespace System.Reflection { - // - // Struct-based list builder that's special cased to avoid allocations for lists of one element. - // + // Helper to build arrays. Special cased to avoid allocations for arrays of one element. internal struct ListBuilder where T : class { + private T[]? _items; + private T _item; + private int _count; + private int _capacity; + public ListBuilder(int capacity) { _items = null; - _item = null; + _item = null!; _count = 0; _capacity = capacity; -#if DEBUG - _toArrayAlreadyCalled = false; -#endif // DEBUG } public T this[int index] @@ -32,23 +33,28 @@ public T this[int index] public T[] ToArray() { -#if DEBUG - // ListBuilder does not always allocate a new array, though the ToArray() name connotates that it does (and in fact, we do pass the results - // of this method across api boundaries.) The minimizing of allocations is desirable, however, so instead, we restrict you to one call per ListBuilder. - Debug.Assert(!_toArrayAlreadyCalled, "Cannot call ListBuilder.ToArray() a second time. Copy the one you already got."); -#endif // DEBUG if (_count == 0) - return Array.Empty(); + return []; + if (_count == 1) - return new T[1] { _item }; + return [_item]; - Array.Resize(ref _items, _count); + if (_count == _items!.Length) + return _items; -#if DEBUG - _toArrayAlreadyCalled = true; -#endif // DEBUG + return _items.AsSpan(0, _count).ToArray(); + } + + [UnscopedRef] + public readonly ReadOnlySpan AsSpan() + { + if (_count == 0) + return default; + + if (_count == 1) + return new ReadOnlySpan(in _item); - return _items; + return _items.AsSpan(0, _count); } public void CopyTo(object[] array, int index) @@ -62,16 +68,10 @@ public void CopyTo(object[] array, int index) return; } - Array.Copy(_items, 0, array, index, _count); + Array.Copy(_items!, 0, array, index, _count); } - public int Count - { - get - { - return _count; - } - } + public int Count => _count; public void Add(T item) { @@ -85,6 +85,7 @@ public void Add(T item) { if (_capacity < 2) _capacity = 4; + _items = new T[_capacity]; _items[0] = _item; } @@ -95,17 +96,10 @@ public void Add(T item) _capacity = newCapacity; } - _items[_count] = item; + _items![_count] = item; } + _count++; } - - private T[] _items; - private T _item; - private int _count; - private int _capacity; -#if DEBUG - private bool _toArrayAlreadyCalled; -#endif // DEBUG } } diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index c9e3d9ff4573a7..01577c29a88193 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -49,94 +49,6 @@ internal enum MemberListType HandleToInfo } - // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element. - private struct ListBuilder where T : class? - { - private T[]? _items; - private T _item; - private int _count; - private int _capacity; - - public ListBuilder(int capacity) - { - _items = null; - _item = null!; - _count = 0; - _capacity = capacity; - } - - public T this[int index] - { - get - { - Debug.Assert(index < Count); - return (_items != null) ? _items[index] : _item; - } - } - - public T[] ToArray() - { - if (_count == 0) - return Array.Empty(); - if (_count == 1) - return new T[1] { _item }; - - Array.Resize(ref _items, _count); - _capacity = _count; - return _items; - } - - public void CopyTo(object?[] array, int index) - { - if (_count == 0) - return; - - if (_count == 1) - { - array[index] = _item; - return; - } - - Array.Copy(_items!, 0, array, index, _count); - } - - public int Count - { - get - { - return _count; - } - } - - public void Add(T item) - { - if (_count == 0) - { - _item = item; - } - else - { - if (_count == 1) - { - if (_capacity < 2) - _capacity = 4; - _items = new T[_capacity]; - _items[0] = _item; - } - else - if (_capacity == _count) - { - int newCapacity = 2 * _capacity; - Array.Resize(ref _items, newCapacity); - _capacity = newCapacity; - } - - _items![_count] = item; - } - _count++; - } - } - #endregion #region Static Members @@ -798,7 +710,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) } // All the methods have the exact same name and sig so return the most derived one. - return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo; + return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.AsSpan()); } } @@ -827,7 +739,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) } if ((bindingAttr & BindingFlags.ExactBinding) != 0) - return System.DefaultBinder.ExactBinding(candidates.ToArray(), types) as ConstructorInfo; + return System.DefaultBinder.ExactBinding(candidates.AsSpan(), types); binder ??= DefaultBinder;