return result;
}
+ public sealed override Array GetEnumValuesAsUnderlyingType()
+ {
+ if (!IsActualEnum)
+ throw new ArgumentException(SR.Arg_MustBeEnum, "enumType");
+
+ return (Array)Enum.GetEnumInfo(this).ValuesAsUnderlyingType.Clone();
+ }
+
internal bool IsActualEnum
=> TryGetEEType(out EETypePtr eeType) && eeType.IsEnum;
}
/// </summary>
protected virtual IComparer Comparer => InvariantComparer.Default;
- private static long GetEnumValue(bool isUnderlyingTypeUInt64, Enum enumVal, CultureInfo? culture)
+ private static long GetEnumValue(bool isUnderlyingTypeUInt64, object enumVal, CultureInfo? culture)
{
return isUnderlyingTypeUInt64 ?
unchecked((long)Convert.ToUInt64(enumVal, culture)) :
string[] values = strValue.Split(',');
foreach (string v in values)
{
- convertedValue |= GetEnumValue(isUnderlyingTypeUInt64, (Enum)Enum.Parse(EnumType, v, true), culture);
+ convertedValue |= GetEnumValue(isUnderlyingTypeUInt64, Enum.Parse(EnumType, v, true), culture);
}
return Enum.ToObject(EnumType, convertedValue);
}
bool isUnderlyingTypeUInt64 = Enum.GetUnderlyingType(EnumType) == typeof(ulong);
List<Enum> flagValues = new List<Enum>();
- Array objValues = Enum.GetValues(EnumType);
+ Array objValues = Enum.GetValuesAsUnderlyingType(EnumType);
long[] ulValues = new long[objValues.Length];
for (int idx = 0; idx < objValues.Length; idx++)
{
- ulValues[idx] = GetEnumValue(isUnderlyingTypeUInt64, (Enum)objValues.GetValue(idx)!, culture);
+ ulValues[idx] = GetEnumValue(isUnderlyingTypeUInt64, objValues.GetValue(idx)!, culture);
}
- long longValue = GetEnumValue(isUnderlyingTypeUInt64, (Enum)value, culture);
+ long longValue = GetEnumValue(isUnderlyingTypeUInt64, value, culture);
bool valueFound = true;
while (valueFound)
{
(TEnum[])GetValues(typeof(TEnum));
#endif
- [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetValues<TEnum> overload instead.")]
+ [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetValues<TEnum> overload or the GetValuesAsUnderlyingType method instead.")]
public static Array GetValues(Type enumType)
{
ArgumentNullException.ThrowIfNull(enumType);
return enumType.GetEnumValues();
}
+ /// <summary>
+ /// Retrieves an array of the values of the underlying type constants in a specified enumeration type.
+ /// </summary>
+ /// <typeparam name="TEnum">An enumeration type.</typeparam>
+ /// /// <remarks>
+ /// This method can be used to get enumeration values when creating an array of the enumeration type is challenging.
+ /// For example, <see cref="T:System.Reflection.MetadataLoadContext" /> or on a platform where runtime codegen is not available.
+ /// </remarks>
+ /// <returns>An array that contains the values of the underlying type constants in enumType.</returns>
+ public static Array GetValuesAsUnderlyingType<TEnum>() where TEnum : struct, Enum =>
+ typeof(TEnum).GetEnumValuesAsUnderlyingType();
+
+ /// <summary>
+ /// Retrieves an array of the values of the underlying type constants in a specified enumeration.
+ /// </summary>
+ /// <param name="enumType">An enumeration type.</param>
+ /// <remarks>
+ /// This method can be used to get enumeration values when creating an array of the enumeration type is challenging.
+ /// For example, <see cref="T:System.Reflection.MetadataLoadContext" /> or on a platform where runtime codegen is not available.
+ /// </remarks>
+ /// <returns>An array that contains the values of the underlying type constants in <paramref name="enumType" />.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// Thrown when the enumeration type is null.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// Thrown when the type is not an enumeration type.
+ /// </exception>
+ public static Array GetValuesAsUnderlyingType(Type enumType)
+ {
+ ArgumentNullException.ThrowIfNull(enumType);
+ return enumType.GetEnumValuesAsUnderlyingType();
+ }
+
[Intrinsic]
public bool HasFlag(Enum flag)
{
public sealed override string GetEnumName(object value) => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override string[] GetEnumNames() => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override Type GetEnumUnderlyingType() => throw new NotSupportedException(SR.NotSupported_SignatureType);
- [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use Enum.GetValues<TEnum> instead.")]
+ [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetEnumValues<TEnum> overload or the GetEnumValuesAsUnderlyingType method instead.")]
public sealed override Array GetEnumValues() => throw new NotSupportedException(SR.NotSupported_SignatureType);
public sealed override Guid GUID => throw new NotSupportedException(SR.NotSupported_SignatureType);
protected sealed override TypeCode GetTypeCodeImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
return new ReadOnlySpan<string>(ret).ToArray();
}
- [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetValues<TEnum> overload instead.")]
+ [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetEnumValues<TEnum> overload or the GetEnumValuesAsUnderlyingType method instead.")]
public override Array GetEnumValues()
{
if (!IsActualEnum)
return ret;
}
+ /// <summary>
+ /// Retrieves an array of the values of the underlying type constants in a specified enumeration type.
+ /// </summary>
+ /// <remarks>
+ /// This method can be used to get enumeration values when creating an array of the enumeration type is challenging.
+ /// For example, <see cref="T:System.Reflection.MetadataLoadContext" /> or on a platform where runtime codegen is not available.
+ /// </remarks>
+ /// <returns>An array that contains the values of the underlying type constants in enumType.</returns>
+ /// <exception cref="ArgumentException">
+ /// Thrown when the type is not Enum
+ /// </exception>
+ public override Array GetEnumValuesAsUnderlyingType()
+ {
+ if (!IsActualEnum)
+ throw new ArgumentException(SR.Arg_MustBeEnum, "enumType");
+
+ // Get all of the values
+ ulong[] values = Enum.InternalGetValues(this);
+
+ switch (RuntimeTypeHandle.GetCorElementType(Enum.InternalGetUnderlyingType(this)))
+ {
+
+ case CorElementType.ELEMENT_TYPE_U1:
+ {
+ var ret = new byte[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (byte)values[i];
+ }
+ return ret;
+ }
+
+ case CorElementType.ELEMENT_TYPE_U2:
+ {
+ var ret = new ushort[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (ushort)values[i];
+ }
+ return ret;
+ }
+
+ case CorElementType.ELEMENT_TYPE_U4:
+ {
+ var ret = new uint[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (uint)values[i];
+ }
+ return ret;
+ }
+
+ case CorElementType.ELEMENT_TYPE_U8:
+ {
+ return (Array)values.Clone();
+ }
+
+ case CorElementType.ELEMENT_TYPE_I1:
+ {
+ var ret = new sbyte[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (sbyte)values[i];
+ }
+ return ret;
+ }
+
+ case CorElementType.ELEMENT_TYPE_I2:
+ {
+ var ret = new short[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (short)values[i];
+ }
+ return ret;
+ }
+
+ case CorElementType.ELEMENT_TYPE_I4:
+ {
+ var ret = new int[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (int)values[i];
+ }
+ return ret;
+ }
+
+ case CorElementType.ELEMENT_TYPE_I8:
+ {
+ var ret = new long[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ ret[i] = (long)values[i];
+ }
+ return ret;
+ }
+ default:
+ throw new InvalidOperationException(SR.InvalidOperation_UnknownEnumType);
+ }
+ }
+
public override Type GetEnumUnderlyingType()
{
if (!IsActualEnum)
return fields[0].FieldType;
}
- [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use Enum.GetValues<TEnum> instead.")]
+ [RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetEnumValues<TEnum> overload or the GetEnumValuesAsUnderlyingType method instead.")]
public virtual Array GetEnumValues()
{
if (!IsEnum)
throw NotImplemented.ByDesign;
}
+ /// <summary>
+ /// Retrieves an array of the values of the underlying type constants in a specified enumeration type.
+ /// </summary>
+ /// <remarks>
+ /// This method can be used to get enumeration values when creating an array of the enumeration type is challenging.
+ /// For example, <see cref="T:System.Reflection.MetadataLoadContext" /> or on a platform where runtime codegen is not available.
+ /// </remarks>
+ /// <returns>An array that contains the values of the underlying type constants in enumType.</returns>
+ /// <exception cref="ArgumentException">
+ /// Thrown when the type is not an enumeration type.
+ /// </exception>
+ public virtual Array GetEnumValuesAsUnderlyingType() => throw new NotSupportedException(SR.NotSupported_SubclassOverride);
+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public virtual Type MakeArrayType() => throw new NotSupportedException();
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
private volatile RoType? _lazyUnderlyingEnumType;
public sealed override Array GetEnumValues() => throw new InvalidOperationException(SR.Arg_InvalidOperation_Reflection);
+#if NET7_0_OR_GREATER
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2085:UnrecognizedReflectionPattern",
+ Justification = "Enum Types are not trimmed.")]
+ public override Array GetEnumValuesAsUnderlyingType()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(SR.Arg_MustBeEnum, "enumType");
+
+ FieldInfo[] enumFields = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+ int numValues = enumFields.Length;
+ Array ret = Type.GetTypeCode(GetEnumUnderlyingType()) switch
+ {
+ TypeCode.Byte => new byte[numValues],
+ TypeCode.SByte => new sbyte[numValues],
+ TypeCode.UInt16 => new ushort[numValues],
+ TypeCode.Int16 => new short[numValues],
+ TypeCode.UInt32 => new uint[numValues],
+ TypeCode.Int32 => new int[numValues],
+ TypeCode.UInt64 => new ulong[numValues],
+ TypeCode.Int64 => new long[numValues],
+ _ => throw new NotSupportedException(),
+ };
+
+ for (int i = 0; i < numValues; i++)
+ {
+ ret.SetValue(enumFields[i].GetRawConstantValue(), i);
+ }
+
+ return ret;
+ }
+#endif
+
// No trust environment to apply these to.
public sealed override bool IsSecurityCritical => throw new InvalidOperationException(SR.InvalidOperation_IsSecurity);
public sealed override bool IsSecuritySafeCritical => throw new InvalidOperationException(SR.InvalidOperation_IsSecurity);
public enum EU8 : ulong { }
public enum EI8 : long { }
+ public enum E_2_I4 : int { min=int.MinValue, zero=0, one=1, max=int.MaxValue}
+ public enum E_2_U4 : uint { min = uint.MinValue, zero = 0, one = 1, max = uint.MaxValue }
+
public class GenericEnumContainer<T>
{
public enum GenericEnum : short { }
}
}
+#if NET7_0_OR_GREATER
+ [Fact]
+ public static void GetEnumValuesAsUnderlyingType()
+ {
+ var intEnumType = typeof(E_2_I4).Project();
+ int[] expectedIntValues = { int.MinValue, 0, 1, int.MaxValue };
+ Array intArr = intEnumType.GetEnumValuesAsUnderlyingType();
+ for (int i = 0; i < intArr.Length; i++)
+ {
+ Assert.Equal(expectedIntValues[i], intArr.GetValue(i));
+ Assert.Equal(Type.GetTypeCode(expectedIntValues[i].GetType()), Type.GetTypeCode(intArr.GetValue(i).GetType()));
+ }
+
+ var uintEnumType = typeof(E_2_U4).Project();
+ uint[] expectesUIntValues = { uint.MinValue, 0, 1, uint.MaxValue };
+ Array uintArr = uintEnumType.GetEnumValuesAsUnderlyingType();
+ for (int i = 0; i < uintArr.Length; i++)
+ {
+ Assert.Equal(expectesUIntValues[i], uintArr.GetValue(i));
+ Assert.Equal(Type.GetTypeCode(expectesUIntValues[i].GetType()), Type.GetTypeCode(uintArr.GetValue(i).GetType()));
+ }
+ }
+#endif
+
[Theory]
[MemberData(nameof(GetTypeCodeTheoryData))]
public static void GettypeCode(TypeWrapper tw, TypeCode expectedTypeCode)
}
[Fact]
+ public static void GetEnumValuesAsUnderlyingType_Int()
+ {
+ GetEnumValuesAsUnderlyingType(typeof(IntEnum), new int[] { 1, 2, 10, 18, 45 });
+ }
+
+ [Fact]
+ public static void GetEnumValuesAsUnderlyingType_UInt()
+ {
+ GetEnumValuesAsUnderlyingType(typeof(UIntEnum), new uint[] { 1, 10 });
+ }
+
+ private static void GetEnumValuesAsUnderlyingType(Type enumType, Array expected)
+ {
+ Assert.Equal(expected, enumType.GetTypeInfo().GetEnumValuesAsUnderlyingType());
+ }
+
+
+ [Fact]
public void GetEnumValues_TypeNotEnum_ThrowsArgumentException()
{
AssertExtensions.Throws<ArgumentException>("enumType", () => typeof(NonGenericClassWithNoInterfaces).GetTypeInfo().GetEnumUnderlyingType());
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; }
- [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetValues<TEnum> overload instead.")]
+ [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetValues<TEnum> overload or the GetValuesAsUnderlyingType method instead.")]
public static System.Array GetValues(System.Type enumType) { throw null; }
public static TEnum[] GetValues<TEnum>() where TEnum : struct, System.Enum { throw null; }
+ public static System.Array GetValuesAsUnderlyingType(System.Type enumType) { throw null; }
+ public static System.Array GetValuesAsUnderlyingType<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 virtual string? GetEnumName(object value) { throw null; }
public virtual string[] GetEnumNames() { throw null; }
public virtual System.Type GetEnumUnderlyingType() { throw null; }
- [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use Enum.GetValues<TEnum> instead.")]
+ [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("It might not be possible to create an array of the enum type at runtime. Use the GetEnumValues<TEnum> overload or the GetEnumValuesAsUnderlyingType method instead.")]
public virtual System.Array GetEnumValues() { throw null; }
+ public virtual System.Array GetEnumValuesAsUnderlyingType() { throw null; }
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents)]
public System.Reflection.EventInfo? GetEvent(string name) { throw null; }
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents)]
AssertExtensions.Throws<ArgumentNullException>("enumType", () => Enum.GetValues(null));
}
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeSByteEnum_ReturnsExpected()
+ {
+ Array expected = new sbyte[] { 1, 2, sbyte.MaxValue, sbyte.MinValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(SByteEnum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<SByteEnum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeByteEnum_ReturnsExpected()
+ {
+ Array expected = new byte[] { byte.MinValue, 1, 2, byte.MaxValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(ByteEnum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<ByteEnum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeInt16Enum_ReturnsExpected()
+ {
+ Array expected = new short[] { 1, 2, short.MaxValue, short.MinValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(Int16Enum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<Int16Enum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeUInt16Enum_ReturnsExpected()
+ {
+ Array expected = new ushort[] { ushort.MinValue, 1, 2, ushort.MaxValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(UInt16Enum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<UInt16Enum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeInt32Enum_ReturnsExpected()
+ {
+ Array expected = new int[] { 1, 2, int.MaxValue, int.MinValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(Int32Enum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<Int32Enum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeUInt32Enum_ReturnsExpected()
+ {
+ Array expected = new uint[] { uint.MinValue, 1, 2, uint.MaxValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(UInt32Enum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<UInt32Enum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeInt64Enum_ReturnsExpected()
+ {
+ Array expected = new long[] { 1, 2, long.MaxValue, long.MinValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(Int64Enum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<Int64Enum>());
+ }
+
+ [Fact]
+ public void GetValuesAsUnderlyingType_InvokeUInt64Enum_ReturnsExpected()
+ {
+ Array expected = new ulong[] { ulong.MinValue, 1, 2, ulong.MaxValue };
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType(typeof(UInt64Enum)));
+ Assert.Equal(expected, Enum.GetValuesAsUnderlyingType<UInt64Enum>());
+ }
+
+ [Fact]
+ public static void GetValuesAsUnderlyingType_NullEnumType_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("enumType", () => Enum.GetValuesAsUnderlyingType(null));
+ }
+
[Theory]
[InlineData(typeof(object))]
[InlineData(typeof(int))]
throw new Exception("GetValues");
}
+ Console.WriteLine("Enum.GetValuesAsUnderlyingType");
+ {
+ if (Enum.GetValuesAsUnderlyingType(typeof(Mine)).GetType() != typeof(int[]))
+ throw new Exception("Enum.GetValuesAsUnderlyingType");
+ }
+
Console.WriteLine("Pattern in LINQ expressions");
{
Type objType = typeof(object);