Skip to content

Commit

Permalink
Add Enum generic overloads (#33589)
Browse files Browse the repository at this point in the history
  • Loading branch information
hughbe authored Jul 13, 2020
1 parent 2d9dbbb commit 7b2e585
Show file tree
Hide file tree
Showing 8 changed files with 780 additions and 515 deletions.
92 changes: 0 additions & 92 deletions src/coreclr/src/System.Private.CoreLib/src/System/Enum.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,6 @@ public abstract partial class Enum
[MethodImpl(MethodImplOptions.InternalCall)]
private extern bool InternalHasFlag(Enum flags);

private class EnumInfo
{
public readonly bool HasFlagsAttribute;
public readonly ulong[] Values;
public readonly string[] Names;

// Each entry contains a list of sorted pair of enum field names and values, sorted by values
public EnumInfo(bool hasFlagsAttribute, ulong[] values, string[] names)
{
HasFlagsAttribute = hasFlagsAttribute;
Values = values;
Names = names;
}
}

private static EnumInfo GetEnumInfo(RuntimeType enumType, bool getNames = true)
{
EnumInfo? entry = enumType.GenericCache as EnumInfo;
Expand All @@ -64,82 +49,5 @@ private static EnumInfo GetEnumInfo(RuntimeType enumType, bool getNames = true)

return entry;
}

internal static ulong[] InternalGetValues(RuntimeType enumType)
{
// Get all of the values
return GetEnumInfo(enumType, false).Values;
}

internal static string[] InternalGetNames(RuntimeType enumType)
{
// Get all of the names
return GetEnumInfo(enumType, true).Names;
}

[Intrinsic]
public bool HasFlag(Enum flag)
{
if (flag == null)
throw new ArgumentNullException(nameof(flag));

if (!this.GetType().IsEquivalentTo(flag.GetType()))
{
throw new ArgumentException(SR.Format(SR.Argument_EnumTypeDoesNotMatch, flag.GetType(), this.GetType()));
}

return InternalHasFlag(flag);
}

public static string? GetName(Type enumType, object value)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumName(value);
}

public static string[] GetNames(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumNames();
}

public static Type GetUnderlyingType(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumUnderlyingType();
}

public static Array GetValues(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumValues();
}

public static bool IsDefined(Type enumType, object value)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));

return enumType.IsEnumDefined(value);
}

private static RuntimeType ValidateRuntimeType(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));
if (!enumType.IsEnum)
throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType));
if (!(enumType is RuntimeType rtType))
throw new ArgumentException(SR.Arg_MustBeType, nameof(enumType));
return rtType;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ public static bool IsDrawingSupported
public static bool SupportsSsl2 => IsWindows && !PlatformDetection.IsWindows10Version1607OrGreater;

#if NETCOREAPP
public static bool IsReflectionEmitSupported = RuntimeFeature.IsDynamicCodeSupported;
public static bool IsReflectionEmitSupported => RuntimeFeature.IsDynamicCodeSupported;
#else
public static bool IsReflectionEmitSupported = true;
public static bool IsReflectionEmitSupported => true;
#endif

public static bool IsInvokingStaticConstructorsSupported => true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Empty.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\EntryPointNotFoundException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Enum.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Enum.EnumInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.SpecialFolder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.SpecialFolderOption.cs" />
Expand Down
23 changes: 23 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Enum.EnumInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System
{
public abstract partial class Enum
{
internal sealed class EnumInfo
{
public readonly bool HasFlagsAttribute;
public readonly ulong[] Values;
public readonly string[] Names;

// Each entry contains a list of sorted pair of enum field names and values, sorted by values
public EnumInfo(bool hasFlagsAttribute, ulong[] values, string[] names)
{
HasFlagsAttribute = hasFlagsAttribute;
Values = values;
Names = names;
}
}
}
}
92 changes: 92 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Enum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,87 @@ internal static ulong ToUInt64(object value)
#endregion

#region Public Static Methods
public static string? GetName<TEnum>(TEnum value) where TEnum : struct, Enum
=> GetName(typeof(TEnum), value);

public static string? GetName(Type enumType, object value)
{
if (enumType is null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumName(value);
}

public static string[] GetNames<TEnum>() where TEnum : struct, Enum
=> GetNames(typeof(TEnum));

public static string[] GetNames(Type enumType)
{
if (enumType is null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumNames();
}

internal static string[] InternalGetNames(RuntimeType enumType)
{
// Get all of the names
return GetEnumInfo(enumType, true).Names;
}

public static Type GetUnderlyingType(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumUnderlyingType();
}

public static TEnum[] GetValues<TEnum>() where TEnum : struct, Enum
=> (TEnum[])GetValues(typeof(TEnum));

public static Array GetValues(Type enumType)
{
if (enumType is null)
throw new ArgumentNullException(nameof(enumType));

return enumType.GetEnumValues();
}

[Intrinsic]
public bool HasFlag(Enum flag)
{
if (flag is null)
throw new ArgumentNullException(nameof(flag));
if (!GetType().IsEquivalentTo(flag.GetType()))
throw new ArgumentException(SR.Format(SR.Argument_EnumTypeDoesNotMatch, flag.GetType(), GetType()));

return InternalHasFlag(flag);
}

internal static ulong[] InternalGetValues(RuntimeType enumType)
{
// Get all of the values
return GetEnumInfo(enumType, false).Values;
}

public static bool IsDefined<TEnum>(TEnum value) where TEnum : struct, Enum
{
RuntimeType enumType = (RuntimeType)typeof(TEnum);
ulong[] ulValues = Enum.InternalGetValues(enumType);
ulong ulValue = Enum.ToUInt64(value);

return Array.BinarySearch(ulValues, ulValue) >= 0;
}

public static bool IsDefined(Type enumType, object value)
{
if (enumType is null)
throw new ArgumentNullException(nameof(enumType));

return enumType.IsEnumDefined(value);
}

public static object Parse(Type enumType, string value) =>
Parse(enumType, value, ignoreCase: false);

Expand Down Expand Up @@ -1141,5 +1222,16 @@ private static object ToObject(Type enumType, bool value) =>
InternalBoxEnum(ValidateRuntimeType(enumType), value ? 1 : 0);

#endregion

private static RuntimeType ValidateRuntimeType(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));
if (!enumType.IsEnum)
throw new ArgumentException(SR.Arg_MustBeEnum, nameof(enumType));
if (!(enumType is RuntimeType rtType))
throw new ArgumentException(SR.Arg_MustBeType, nameof(enumType));
return rtType;
}
}
}
4 changes: 4 additions & 0 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1808,12 +1808,16 @@ protected Enum() { }
public static string Format(System.Type enumType, object value, string format) { throw null; }
public override int GetHashCode() { throw null; }
public static string? GetName(System.Type enumType, object value) { throw null; }
public static string? GetName<TEnum>(TEnum value) where TEnum : struct, System.Enum { throw null; }
public static string[] GetNames(System.Type enumType) { throw null; }
public static string[] GetNames<TEnum>() where TEnum: struct, System.Enum { throw null; }
public System.TypeCode GetTypeCode() { throw null; }
public static System.Type GetUnderlyingType(System.Type enumType) { throw null; }
public static System.Array GetValues(System.Type enumType) { throw null; }
public static TEnum[] GetValues<TEnum>() where TEnum : struct, System.Enum { throw null; }
public bool HasFlag(System.Enum flag) { throw null; }
public static bool IsDefined(System.Type enumType, object value) { throw null; }
public static bool IsDefined<TEnum>(TEnum value) where TEnum : struct, System.Enum { throw null; }
public static object Parse(System.Type enumType, string value) { throw null; }
public static object Parse(System.Type enumType, string value, bool ignoreCase) { throw null; }
public static TEnum Parse<TEnum>(string value) where TEnum : struct { throw null; }
Expand Down
Loading

0 comments on commit 7b2e585

Please sign in to comment.