summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Enum.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Enum.cs')
-rw-r--r--src/mscorlib/src/System/Enum.cs1265
1 files changed, 1265 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Enum.cs b/src/mscorlib/src/System/Enum.cs
new file mode 100644
index 0000000000..a8104556e4
--- /dev/null
+++ b/src/mscorlib/src/System/Enum.cs
@@ -0,0 +1,1265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection;
+using System.Text;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
+ {
+ #region Private Constants
+ private const char enumSeparatorChar = ',';
+ private const String enumSeparatorString = ", ";
+ #endregion
+
+ #region Private Static Methods
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static TypeValuesAndNames GetCachedValuesAndNames(RuntimeType enumType, bool getNames)
+ {
+ TypeValuesAndNames entry = enumType.GenericCache as TypeValuesAndNames;
+
+ if (entry == null || (getNames && entry.Names == null))
+ {
+ ulong[] values = null;
+ String[] names = null;
+ bool isFlags = enumType.IsDefined(typeof(System.FlagsAttribute), false);
+
+ GetEnumValuesAndNames(
+ enumType.GetTypeHandleInternal(),
+ JitHelpers.GetObjectHandleOnStack(ref values),
+ JitHelpers.GetObjectHandleOnStack(ref names),
+ getNames);
+
+ entry = new TypeValuesAndNames(isFlags, values, names);
+ enumType.GenericCache = entry;
+ }
+
+ return entry;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private unsafe String InternalFormattedHexString()
+ {
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ case CorElementType.U1:
+ return (*(byte*)pValue).ToString("X2", null);
+ case CorElementType.Boolean:
+ // direct cast from bool to byte is not allowed
+ return Convert.ToByte(*(bool*)pValue).ToString("X2", null);
+ case CorElementType.I2:
+ case CorElementType.U2:
+ case CorElementType.Char:
+ return (*(ushort*)pValue).ToString("X4", null);
+ case CorElementType.I4:
+ case CorElementType.U4:
+ return (*(uint*)pValue).ToString("X8", null);
+ case CorElementType.I8:
+ case CorElementType.U8:
+ return (*(ulong*)pValue).ToString("X16", null);
+ default:
+ Contract.Assert(false, "Invalid Object type in Format");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+ }
+
+ private static String InternalFormattedHexString(object value)
+ {
+ TypeCode typeCode = Convert.GetTypeCode(value);
+
+ switch (typeCode)
+ {
+ case TypeCode.SByte:
+ return ((byte)(sbyte)value).ToString("X2", null);
+ case TypeCode.Byte:
+ return ((byte)value).ToString("X2", null);
+ case TypeCode.Boolean:
+ // direct cast from bool to byte is not allowed
+ return Convert.ToByte((bool)value).ToString("X2", null);
+ case TypeCode.Int16:
+ return ((UInt16)(Int16)value).ToString("X4", null);
+ case TypeCode.UInt16:
+ return ((UInt16)value).ToString("X4", null);
+ case TypeCode.Char:
+ return ((UInt16)(Char)value).ToString("X4", null);
+ case TypeCode.UInt32:
+ return ((UInt32)value).ToString("X8", null);
+ case TypeCode.Int32:
+ return ((UInt32)(Int32)value).ToString("X8", null);
+ case TypeCode.UInt64:
+ return ((UInt64)value).ToString("X16", null);
+ case TypeCode.Int64:
+ return ((UInt64)(Int64)value).ToString("X16", null);
+ // All unsigned types will be directly cast
+ default:
+ Contract.Assert(false, "Invalid Object type in Format");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+
+ internal static String GetEnumName(RuntimeType eT, ulong ulValue)
+ {
+ Contract.Requires(eT != null);
+ ulong[] ulValues = Enum.InternalGetValues(eT);
+ int index = Array.BinarySearch(ulValues, ulValue);
+
+ if (index >= 0)
+ {
+ string[] names = Enum.InternalGetNames(eT);
+ return names[index];
+ }
+
+ return null; // return null so the caller knows to .ToString() the input
+ }
+
+ private static String InternalFormat(RuntimeType eT, ulong value)
+ {
+ Contract.Requires(eT != null);
+
+ // These values are sorted by value. Don't change this
+ TypeValuesAndNames entry = GetCachedValuesAndNames(eT, true);
+
+ if (!entry.IsFlag) // Not marked with Flags attribute
+ {
+ return Enum.GetEnumName(eT, value);
+ }
+ else // These are flags OR'ed together (We treat everything as unsigned types)
+ {
+ return InternalFlagsFormat(eT, entry, value);
+ }
+ }
+
+ private static String InternalFlagsFormat(RuntimeType eT,ulong result)
+ {
+ // These values are sorted by value. Don't change this
+ TypeValuesAndNames entry = GetCachedValuesAndNames(eT, true);
+
+ return InternalFlagsFormat(eT, entry, result);
+ }
+
+ private static String InternalFlagsFormat(RuntimeType eT, TypeValuesAndNames entry, ulong result)
+ {
+ Contract.Requires(eT != null);
+
+ String[] names = entry.Names;
+ ulong[] values = entry.Values;
+ Contract.Assert(names.Length == values.Length);
+
+ int index = values.Length - 1;
+ StringBuilder retval = new StringBuilder();
+ bool firstTime = true;
+ ulong saveResult = result;
+
+ // We will not optimize this code further to keep it maintainable. There are some boundary checks that can be applied
+ // to minimize the comparsions required. This code works the same for the best/worst case. In general the number of
+ // items in an enum are sufficiently small and not worth the optimization.
+ while (index >= 0)
+ {
+ if ((index == 0) && (values[index] == 0))
+ break;
+
+ if ((result & values[index]) == values[index])
+ {
+ result -= values[index];
+ if (!firstTime)
+ retval.Insert(0, enumSeparatorString);
+
+ retval.Insert(0, names[index]);
+ firstTime = false;
+ }
+
+ index--;
+ }
+
+ // We were unable to represent this number as a bitwise or of valid flags
+ if (result != 0)
+ return null; // return null so the caller knows to .ToString() the input
+
+ // For the case when we have zero
+ if (saveResult == 0)
+ {
+ if (values.Length > 0 && values[0] == 0)
+ return names[0]; // Zero was one of the enum values.
+ else
+ return "0";
+ }
+ else
+ {
+ return retval.ToString(); // Return the string representation
+ }
+ }
+
+ internal static ulong ToUInt64(Object value)
+ {
+ // Helper function to silently convert the value to UInt64 from the other base types for enum without throwing an exception.
+ // This is need since the Convert functions do overflow checks.
+ TypeCode typeCode = Convert.GetTypeCode(value);
+
+ ulong result;
+ switch (typeCode)
+ {
+ case TypeCode.SByte:
+ result = (ulong)(sbyte)value;
+ break;
+ case TypeCode.Byte:
+ result = (byte)value;
+ break;
+ case TypeCode.Boolean:
+ // direct cast from bool to byte is not allowed
+ result = Convert.ToByte((bool)value);
+ break;
+ case TypeCode.Int16:
+ result = (ulong)(Int16)value;
+ break;
+ case TypeCode.UInt16:
+ result = (UInt16)value;
+ break;
+ case TypeCode.Char:
+ result = (UInt16)(Char)value;
+ break;
+ case TypeCode.UInt32:
+ result = (UInt32)value;
+ break;
+ case TypeCode.Int32:
+ result = (ulong)(int)value;
+ break;
+ case TypeCode.UInt64:
+ result = (ulong)value;
+ break;
+ case TypeCode.Int64:
+ result = (ulong)(Int64)value;
+ break;
+ // All unsigned types will be directly cast
+ default:
+ Contract.Assert(false, "Invalid Object type in ToUInt64");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int InternalCompareTo(Object o1, Object o2);
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern RuntimeType InternalGetUnderlyingType(RuntimeType enumType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [System.Security.SuppressUnmanagedCodeSecurity]
+ private static extern void GetEnumValuesAndNames(RuntimeTypeHandle enumType, ObjectHandleOnStack values, ObjectHandleOnStack names, bool getNames);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object InternalBoxEnum(RuntimeType enumType, long value);
+ #endregion
+
+ #region Public Static Methods
+ private enum ParseFailureKind
+ {
+ None = 0,
+ Argument = 1,
+ ArgumentNull = 2,
+ ArgumentWithParameter = 3,
+ UnhandledException = 4
+ }
+
+ // This will store the result of the parsing.
+ private struct EnumResult
+ {
+ internal object parsedEnum;
+ internal bool canThrow;
+ internal ParseFailureKind m_failure;
+ internal string m_failureMessageID;
+ internal string m_failureParameter;
+ internal object m_failureMessageFormatArgument;
+ internal Exception m_innerException;
+
+ internal void SetFailure(Exception unhandledException)
+ {
+ m_failure = ParseFailureKind.UnhandledException;
+ m_innerException = unhandledException;
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureParameter)
+ {
+ m_failure = failure;
+ m_failureParameter = failureParameter;
+ if (canThrow)
+ throw GetEnumParseException();
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument)
+ {
+ m_failure = failure;
+ m_failureMessageID = failureMessageID;
+ m_failureMessageFormatArgument = failureMessageFormatArgument;
+ if (canThrow)
+ throw GetEnumParseException();
+ }
+ internal Exception GetEnumParseException()
+ {
+ switch (m_failure)
+ {
+ case ParseFailureKind.Argument:
+ return new ArgumentException(Environment.GetResourceString(m_failureMessageID));
+
+ case ParseFailureKind.ArgumentNull:
+ return new ArgumentNullException(m_failureParameter);
+
+ case ParseFailureKind.ArgumentWithParameter:
+ return new ArgumentException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument));
+
+ case ParseFailureKind.UnhandledException:
+ return m_innerException;
+
+ default:
+ Contract.Assert(false, "Unknown EnumParseFailure: " + m_failure);
+ return new ArgumentException(Environment.GetResourceString("Arg_EnumValueNotFound"));
+ }
+ }
+ }
+
+ public static bool TryParse<TEnum>(String value, out TEnum result) where TEnum : struct
+ {
+ return TryParse(value, false, out result);
+ }
+
+ public static bool TryParse<TEnum>(String value, bool ignoreCase, out TEnum result) where TEnum : struct
+ {
+ result = default(TEnum);
+ EnumResult parseResult = new EnumResult();
+ bool retValue;
+
+ if (retValue = TryParseEnum(typeof(TEnum), value, ignoreCase, ref parseResult))
+ result = (TEnum)parseResult.parsedEnum;
+ return retValue;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object Parse(Type enumType, String value)
+ {
+ return Parse(enumType, value, false);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object Parse(Type enumType, String value, bool ignoreCase)
+ {
+ EnumResult parseResult = new EnumResult() { canThrow = true };
+ if (TryParseEnum(enumType, value, ignoreCase, ref parseResult))
+ return parseResult.parsedEnum;
+ else
+ throw parseResult.GetEnumParseException();
+ }
+
+ private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, ref EnumResult parseResult)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+
+ if (value == null) {
+ parseResult.SetFailure(ParseFailureKind.ArgumentNull, "value");
+ return false;
+ }
+
+ int firstNonWhitespaceIndex = -1;
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (!Char.IsWhiteSpace(value[i]))
+ {
+ firstNonWhitespaceIndex = i;
+ break;
+ }
+ }
+ if (firstNonWhitespaceIndex == -1) {
+ parseResult.SetFailure(ParseFailureKind.Argument, "Arg_MustContainEnumInfo", null);
+ return false;
+ }
+
+ // We have 2 code paths here. One if they are values else if they are Strings.
+ // values will have the first character as as number or a sign.
+ ulong result = 0;
+
+ char firstNonWhitespaceChar = value[firstNonWhitespaceIndex];
+ if (Char.IsDigit(firstNonWhitespaceChar) || firstNonWhitespaceChar == '-' || firstNonWhitespaceChar == '+')
+ {
+ Type underlyingType = GetUnderlyingType(enumType);
+ Object temp;
+
+ try
+ {
+ value = value.Trim();
+ temp = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
+ parseResult.parsedEnum = ToObject(enumType, temp);
+ return true;
+ }
+ catch (FormatException)
+ { // We need to Parse this as a String instead. There are cases
+ // when you tlbimp enums that can have values of the form "3D".
+ // Don't fix this code.
+ }
+ catch (Exception ex)
+ {
+ if (parseResult.canThrow)
+ throw;
+ else
+ {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ }
+ }
+
+ // Find the field. Let's assume that these are always static classes
+ // because the class is an enum.
+ TypeValuesAndNames entry = GetCachedValuesAndNames(rtType, true);
+ String[] enumNames = entry.Names;
+ ulong[] enumValues = entry.Values;
+
+ StringComparison comparison = ignoreCase ?
+ StringComparison.OrdinalIgnoreCase :
+ StringComparison.Ordinal;
+
+ int valueIndex = firstNonWhitespaceIndex;
+ while (valueIndex <= value.Length) // '=' is to handle invalid case of an ending comma
+ {
+ // Find the next separator, if there is one, otherwise the end of the string.
+ int endIndex = value.IndexOf(enumSeparatorChar, valueIndex);
+ if (endIndex == -1)
+ {
+ endIndex = value.Length;
+ }
+
+ // Shift the starting and ending indices to eliminate whitespace
+ int endIndexNoWhitespace = endIndex;
+ while (valueIndex < endIndex && Char.IsWhiteSpace(value[valueIndex])) valueIndex++;
+ while (endIndexNoWhitespace > valueIndex && Char.IsWhiteSpace(value[endIndexNoWhitespace - 1])) endIndexNoWhitespace--;
+ int valueSubstringLength = endIndexNoWhitespace - valueIndex;
+
+ // Try to match this substring against each enum name
+ bool success = false;
+ for (int i = 0; i < enumNames.Length; i++)
+ {
+ if (enumNames[i].Length == valueSubstringLength &&
+ string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0)
+ {
+ result |= enumValues[i];
+ success = true;
+ break;
+ }
+ }
+
+ // If we couldn't find a match, throw an argument exception.
+ if (!success)
+ {
+ // Not found, throw an argument exception.
+ parseResult.SetFailure(ParseFailureKind.ArgumentWithParameter, "Arg_EnumValueNotFound", value);
+ return false;
+ }
+
+ // Move our pointer to the ending index to go again.
+ valueIndex = endIndex + 1;
+ }
+
+ try
+ {
+ parseResult.parsedEnum = ToObject(enumType, result);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ if (parseResult.canThrow)
+ throw;
+ else
+ {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Type GetUnderlyingType(Type enumType)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumUnderlyingType();
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Array GetValues(Type enumType)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumValues();
+ }
+
+ internal static ulong[] InternalGetValues(RuntimeType enumType)
+ {
+ // Get all of the values
+ return GetCachedValuesAndNames(enumType, false).Values;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static String GetName(Type enumType, Object value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumName(value);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static String[] GetNames(Type enumType)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumNames();
+ }
+
+ internal static String[] InternalGetNames(RuntimeType enumType)
+ {
+ // Get all of the names
+ return GetCachedValuesAndNames(enumType, true).Names;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, Object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Delegate rest of error checking to the other functions
+ TypeCode typeCode = Convert.GetTypeCode(value);
+
+ switch (typeCode)
+ {
+ case TypeCode.Int32 :
+ return ToObject(enumType, (int)value);
+
+ case TypeCode.SByte :
+ return ToObject(enumType, (sbyte)value);
+
+ case TypeCode.Int16 :
+ return ToObject(enumType, (short)value);
+
+ case TypeCode.Int64 :
+ return ToObject(enumType, (long)value);
+
+ case TypeCode.UInt32 :
+ return ToObject(enumType, (uint)value);
+
+ case TypeCode.Byte :
+ return ToObject(enumType, (byte)value);
+
+ case TypeCode.UInt16 :
+ return ToObject(enumType, (ushort)value);
+
+ case TypeCode.UInt64 :
+ return ToObject(enumType, (ulong)value);
+
+ case TypeCode.Char:
+ return ToObject(enumType, (char)value);
+
+ case TypeCode.Boolean:
+ return ToObject(enumType, (bool)value);
+
+ default:
+ // All unsigned types will be directly cast
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+ }
+ }
+
+ [Pure]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static bool IsDefined(Type enumType, Object value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.EndContractBlock();
+
+ return enumType.IsEnumDefined(value);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static String Format(Type enumType, Object value, String format)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (format == null)
+ throw new ArgumentNullException("format");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+
+ // Check if both of them are of the same type
+ Type valueType = value.GetType();
+
+ Type underlyingType = GetUnderlyingType(enumType);
+
+ // If the value is an Enum then we need to extract the underlying value from it
+ if (valueType.IsEnum) {
+
+ if (!valueType.IsEquivalentTo(enumType))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), enumType.ToString()));
+
+ if (format.Length != 1)
+ {
+ // all acceptable format string are of length 1
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+ return ((Enum)value).ToString(format);
+ }
+ // The value must be of the same type as the Underlying type of the Enum
+ else if (valueType != underlyingType) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumFormatUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+ }
+ if (format.Length != 1)
+ {
+ // all acceptable format string are of length 1
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+
+ char formatCh = format[0];
+ if (formatCh == 'G' || formatCh == 'g')
+ return GetEnumName(rtType, ToUInt64(value));
+
+ if (formatCh == 'D' || formatCh == 'd')
+ return value.ToString();
+
+ if (formatCh == 'X' || formatCh == 'x')
+ return InternalFormattedHexString(value);
+
+ if (formatCh == 'F' || formatCh == 'f')
+ return Enum.InternalFlagsFormat(rtType, ToUInt64(value)) ?? value.ToString();
+
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+
+ #endregion
+
+ #region Definitions
+ private class TypeValuesAndNames
+ {
+ // Each entry contains a list of sorted pair of enum field names and values, sorted by values
+ public TypeValuesAndNames(bool isFlag, ulong[] values, String[] names)
+ {
+ this.IsFlag = isFlag;
+ this.Values = values;
+ this.Names = names;
+ }
+
+ public bool IsFlag;
+ public ulong[] Values;
+ public String[] Names;
+ }
+ #endregion
+
+ #region Private Methods
+ [System.Security.SecuritySafeCritical]
+ internal unsafe Object GetValue()
+ {
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ return *(sbyte*)pValue;
+ case CorElementType.U1:
+ return *(byte*)pValue;
+ case CorElementType.Boolean:
+ return *(bool*)pValue;
+ case CorElementType.I2:
+ return *(short*)pValue;
+ case CorElementType.U2:
+ return *(ushort*)pValue;
+ case CorElementType.Char:
+ return *(char*)pValue;
+ case CorElementType.I4:
+ return *(int*)pValue;
+ case CorElementType.U4:
+ return *(uint*)pValue;
+ case CorElementType.R4:
+ return *(float*)pValue;
+ case CorElementType.I8:
+ return *(long*)pValue;
+ case CorElementType.U8:
+ return *(ulong*)pValue;
+ case CorElementType.R8:
+ return *(double*)pValue;
+ case CorElementType.I:
+ return *(IntPtr*)pValue;
+ case CorElementType.U:
+ return *(UIntPtr*)pValue;
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ return null;
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private unsafe ulong ToUInt64()
+ {
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ return (ulong)*(sbyte*)pValue;
+ case CorElementType.U1:
+ return *(byte*)pValue;
+ case CorElementType.Boolean:
+ return Convert.ToUInt64(*(bool*)pValue, CultureInfo.InvariantCulture);
+ case CorElementType.I2:
+ return (ulong)*(short*)pValue;
+ case CorElementType.U2:
+ case CorElementType.Char:
+ return *(ushort*)pValue;
+ case CorElementType.I4:
+ return (ulong)*(int*)pValue;
+ case CorElementType.U4:
+ case CorElementType.R4:
+ return *(uint*)pValue;
+ case CorElementType.I8:
+ return (ulong)*(long*)pValue;
+ case CorElementType.U8:
+ case CorElementType.R8:
+ return *(ulong*)pValue;
+ case CorElementType.I:
+ if (IntPtr.Size == 8)
+ {
+ return *(ulong*)pValue;
+ }
+ else
+ {
+ return (ulong)*(int*)pValue;
+ }
+ case CorElementType.U:
+ if (IntPtr.Size == 8)
+ {
+ return *(ulong*)pValue;
+ }
+ else
+ {
+ return *(uint*)pValue;
+ }
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ return 0;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool InternalHasFlag(Enum flags);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern CorElementType InternalGetCorElementType();
+
+ #endregion
+
+ #region Object Overrides
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern override bool Equals(Object obj);
+
+ [System.Security.SecuritySafeCritical]
+ public override unsafe int GetHashCode()
+ {
+ // Avoid boxing by inlining GetValue()
+ // return GetValue().GetHashCode();
+
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ return (*(sbyte*)pValue).GetHashCode();
+ case CorElementType.U1:
+ return (*(byte*)pValue).GetHashCode();
+ case CorElementType.Boolean:
+ return (*(bool*)pValue).GetHashCode();
+ case CorElementType.I2:
+ return (*(short*)pValue).GetHashCode();
+ case CorElementType.U2:
+ return (*(ushort*)pValue).GetHashCode();
+ case CorElementType.Char:
+ return (*(char*)pValue).GetHashCode();
+ case CorElementType.I4:
+ return (*(int*)pValue).GetHashCode();
+ case CorElementType.U4:
+ return (*(uint*)pValue).GetHashCode();
+ case CorElementType.R4:
+ return (*(float*)pValue).GetHashCode();
+ case CorElementType.I8:
+ return (*(long*)pValue).GetHashCode();
+ case CorElementType.U8:
+ return (*(ulong*)pValue).GetHashCode();
+ case CorElementType.R8:
+ return (*(double*)pValue).GetHashCode();
+ case CorElementType.I:
+ return (*(IntPtr*)pValue).GetHashCode();
+ case CorElementType.U:
+ return (*(UIntPtr*)pValue).GetHashCode();
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ return 0;
+ }
+ }
+ }
+
+ public override String ToString()
+ {
+ // Returns the value in a human readable format. For PASCAL style enums who's value maps directly the name of the field is returned.
+ // For PASCAL style enums who's values do not map directly the decimal value of the field is returned.
+ // For BitFlags (indicated by the Flags custom attribute): If for each bit that is set in the value there is a corresponding constant
+ //(a pure power of 2), then the OR string (ie "Red | Yellow") is returned. Otherwise, if the value is zero or if you can't create a string that consists of
+ // pure powers of 2 OR-ed together, you return a hex value
+
+
+ // Try to see if its one of the enum values, then we return a String back else the value
+ return Enum.InternalFormat((RuntimeType)GetType(), ToUInt64()) ?? GetValue().ToString();
+ }
+ #endregion
+
+ #region IFormattable
+ [Obsolete("The provider argument is not used. Please use ToString(String).")]
+ public String ToString(String format, IFormatProvider provider)
+ {
+ return ToString(format);
+ }
+ #endregion
+
+ #region IComparable
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int CompareTo(Object target)
+ {
+ const int retIncompatibleMethodTables = 2; // indicates that the method tables did not match
+ const int retInvalidEnumType = 3; // indicates that the enum was of an unknown/unsupported unerlying type
+
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ int ret = InternalCompareTo(this, target);
+
+ if (ret < retIncompatibleMethodTables)
+ {
+ // -1, 0 and 1 are the normal return codes
+ return ret;
+ }
+ else if (ret == retIncompatibleMethodTables)
+ {
+ Type thisType = this.GetType();
+ Type targetType = target.GetType();
+
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType",
+ targetType.ToString(), thisType.ToString()));
+ }
+ else
+ {
+ // assert valid return code (3)
+ Contract.Assert(ret == retInvalidEnumType, "Enum.InternalCompareTo return code was invalid");
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+ #endregion
+
+ #region Public Methods
+ public String ToString(String format) {
+ char formatCh;
+ if (format == null || format.Length == 0)
+ formatCh = 'G';
+ else if (format.Length != 1)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ else
+ formatCh = format[0];
+
+ if (formatCh == 'G' || formatCh == 'g')
+ return ToString();
+
+ if (formatCh == 'D' || formatCh == 'd')
+ return GetValue().ToString();
+
+ if (formatCh == 'X' || formatCh == 'x')
+ return InternalFormattedHexString();
+
+ if (formatCh == 'F' || formatCh == 'f')
+ return InternalFlagsFormat((RuntimeType)GetType(), ToUInt64()) ?? GetValue().ToString();
+
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+
+ [Obsolete("The provider argument is not used. Please use ToString().")]
+ public String ToString(IFormatProvider provider)
+ {
+ return ToString();
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public Boolean HasFlag(Enum flag) {
+ if (flag == null)
+ throw new ArgumentNullException("flag");
+ Contract.EndContractBlock();
+
+ if (!this.GetType().IsEquivalentTo(flag.GetType())) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EnumTypeDoesNotMatch", flag.GetType(), this.GetType()));
+ }
+
+ return InternalHasFlag(flag);
+ }
+
+ #endregion
+
+ #region IConvertable
+ public TypeCode GetTypeCode()
+ {
+ Type enumType = this.GetType();
+ Type underlyingType = GetUnderlyingType(enumType);
+
+ if (underlyingType == typeof(Int32))
+ {
+ return TypeCode.Int32;
+ }
+
+ if (underlyingType == typeof(sbyte))
+ {
+ return TypeCode.SByte;
+ }
+
+ if (underlyingType == typeof(Int16))
+ {
+ return TypeCode.Int16;
+ }
+
+ if (underlyingType == typeof(Int64))
+ {
+ return TypeCode.Int64;
+ }
+
+ if (underlyingType == typeof(UInt32))
+ {
+ return TypeCode.UInt32;
+ }
+
+ if (underlyingType == typeof(byte))
+ {
+ return TypeCode.Byte;
+ }
+
+ if (underlyingType == typeof(UInt16))
+ {
+ return TypeCode.UInt16;
+ }
+
+ if (underlyingType == typeof(UInt64))
+ {
+ return TypeCode.UInt64;
+ }
+
+ if (underlyingType == typeof(Boolean))
+ {
+ return TypeCode.Boolean;
+ }
+
+ if (underlyingType == typeof(Char))
+ {
+ return TypeCode.Char;
+ }
+
+ Contract.Assert(false, "Unknown underlying type.");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Enum", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ #endregion
+
+ #region ToObject
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, sbyte value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, short value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, int value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, byte value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, ushort value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, uint value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, long value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, ulong value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, unchecked((long)value));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Object ToObject(Type enumType, char value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Object ToObject(Type enumType, bool value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value ? 1 : 0);
+ }
+ #endregion
+ }
+}