Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid generic virtual methods in enum infrastructure #83063

Merged
merged 2 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ public abstract object ActivatorCreateInstance(

public abstract Assembly[] GetLoadedAssemblies();

public abstract EnumInfo<TUnderlyingValue> GetEnumInfo<TUnderlyingValue>(Type type)
where TUnderlyingValue : struct, INumber<TUnderlyingValue>;
public abstract EnumInfo GetEnumInfo(Type type, Func<Type, string[], object[], bool, EnumInfo> create);

public abstract DynamicInvokeInfo GetDelegateDynamicInvokeInfo(Type type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ internal static EnumInfo<TUnderlyingValue> GetEnumInfo<TUnderlyingValue>(Type en
Debug.Assert(enumType is RuntimeType);
Debug.Assert(enumType.IsEnum);

return ReflectionAugments.ReflectionCoreCallbacks.GetEnumInfo<TUnderlyingValue>(enumType);
return (EnumInfo<TUnderlyingValue>)ReflectionAugments.ReflectionCoreCallbacks.GetEnumInfo(enumType,
static (underlyingType, names, valuesAsObject, isFlags) =>
{
// Only after we've sorted, create the underlying array.
var values = new TUnderlyingValue[valuesAsObject.Length];
for (int i = 0; i < valuesAsObject.Length; i++)
values[i] = (TUnderlyingValue)valuesAsObject[i];
return new EnumInfo<TUnderlyingValue>(underlyingType, values, names, isFlags);
});
}
#pragma warning restore

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,11 @@ public sealed override void MakeTypedReference(object target, FieldInfo[] flds,

public sealed override Assembly[] GetLoadedAssemblies() => RuntimeAssemblyInfo.GetLoadedAssemblies();

public sealed override EnumInfo<TUnderlyingValue> GetEnumInfo<TUnderlyingValue>(Type type)
public sealed override EnumInfo GetEnumInfo(Type type, Func<Type, string[], object[], bool, EnumInfo> create)
{
RuntimeTypeInfo runtimeType = type.CastToRuntimeTypeInfo();

EnumInfo<TUnderlyingValue>? info = runtimeType.GenericCache as EnumInfo<TUnderlyingValue>;
var info = runtimeType.GenericCache as EnumInfo;
if (info != null)
return info;

Expand All @@ -418,12 +418,8 @@ public sealed override EnumInfo<TUnderlyingValue> GetEnumInfo<TUnderlyingValue>(
// That codepath would bring functionality to compare everything that was ever allocated in the program.
ArraySortHelper<object, string>.IntrospectiveSort(unsortedValues, unsortedNames, EnumUnderlyingTypeComparer.Instance);

// Only after we've sorted, create the underlying array.
var values = new TUnderlyingValue[unsortedValues.Length];
for (int i = 0; i < unsortedValues.Length; i++)
values[i] = (TUnderlyingValue)unsortedValues[i];
info = create(RuntimeAugments.GetEnumUnderlyingType(type.TypeHandle), unsortedNames, unsortedValues, isFlags);

info = new EnumInfo<TUnderlyingValue>(RuntimeAugments.GetEnumUnderlyingType(runtimeType.TypeHandle), values, unsortedNames, isFlags);
runtimeType.GenericCache = info;
return info;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace Internal.Reflection
{
internal class ReflectionCoreCallbacksImplementation : ReflectionCoreCallbacks
{
public override EnumInfo<TUnderlyingValue> GetEnumInfo<TUnderlyingValue>(Type type) =>
new EnumInfo<TUnderlyingValue>(
public override EnumInfo GetEnumInfo(Type type, Func<Type, string[], object[], bool, EnumInfo> create) =>
create(
RuntimeAugments.GetEnumUnderlyingType(type.TypeHandle),
values: Array.Empty<TUnderlyingValue>(),
names: Array.Empty<string>(),
isFlags: false);
Array.Empty<string>(),
Array.Empty<object>(),
false);

public override DynamicInvokeInfo GetDelegateDynamicInvokeInfo(Type type)
=> throw new NotSupportedException(SR.Reflection_Disabled);
Expand Down