5 // Miguel de Icaza (miguel@ximian.com)
6 // Nick Drochak (ndrochak@gol.com)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 // (C) Ximian, Inc. http://www.ximian.com
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System
.Collections
;
37 using System
.Globalization
;
38 using System
.Runtime
.CompilerServices
;
39 using System
.Runtime
.InteropServices
;
43 internal struct MonoEnumInfo
46 internal Array values
;
47 internal string[] names
;
48 internal Hashtable name_hash
;
50 static Hashtable cache
;
51 static Hashtable global_cache
;
52 static object global_cache_monitor
;
54 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
55 private static extern void get_enum_info (Type enumType
, out MonoEnumInfo info
);
58 // These comparers are needed because enumerations must be compared
59 // using unsigned values so that negative numbers can be looked up
62 internal static SByteComparer sbyte_comparer
= new SByteComparer ();
63 internal static ShortComparer short_comparer
= new ShortComparer ();
64 internal static IntComparer int_comparer
= new IntComparer ();
65 internal static LongComparer long_comparer
= new LongComparer ();
67 internal class SByteComparer
: IComparer
, System
.Collections
.Generic
.IComparer
<sbyte>
69 public int Compare (object x
, object y
)
74 return ((byte) ix
) - ((byte) iy
);
77 public int Compare (sbyte ix
, sbyte iy
)
79 return ((byte) ix
) - ((byte) iy
);
83 internal class ShortComparer
: IComparer
, System
.Collections
.Generic
.IComparer
<short>
85 public int Compare (object x
, object y
)
90 return ((ushort) ix
) - ((ushort) iy
);
93 public int Compare (short ix
, short iy
)
95 return ((ushort) ix
) - ((ushort) iy
);
99 internal class IntComparer
: IComparer
, System
.Collections
.Generic
.IComparer
<int>
101 public int Compare (object x
, object y
)
109 if (((uint) ix
) < ((uint) iy
))
114 public int Compare (int ix
, int iy
)
119 if (((uint) ix
) < ((uint) iy
))
125 internal class LongComparer
: IComparer
, System
.Collections
.Generic
.IComparer
<long>
127 public int Compare (object x
, object y
)
134 if (((ulong) ix
) < ((ulong) iy
))
139 public int Compare (long ix
, long iy
)
143 if (((ulong) ix
) < ((ulong) iy
))
149 static MonoEnumInfo ()
151 global_cache_monitor
= new object ();
152 global_cache
= new Hashtable ();
155 static Hashtable Cache
{
158 cache
= new Hashtable ();
163 private MonoEnumInfo (MonoEnumInfo other
)
166 values
= other
.values
;
168 name_hash
= other
.name_hash
;
171 internal static void GetInfo (Type enumType
, out MonoEnumInfo info
)
173 /* First check the thread-local cache without locking */
174 if (Cache
.ContainsKey (enumType
)) {
175 info
= (MonoEnumInfo
) cache
[enumType
];
178 /* Threads could die, so keep a global cache too */
179 lock (global_cache_monitor
) {
180 if (global_cache
.ContainsKey (enumType
)) {
181 object boxedInfo
= global_cache
[enumType
];
182 cache
[enumType
] = boxedInfo
;
183 info
= (MonoEnumInfo
)boxedInfo
;
188 get_enum_info (enumType
, out info
);
191 if (info
.values
is int [])
193 else if (info
.values
is short [])
195 else if (info
.values
is sbyte [])
197 else if (info
.values
is long [])
200 Array
.Sort (info
.values
, info
.names
, ic
);
201 if (info
.names
.Length
> 50) {
202 info
.name_hash
= new Hashtable (info
.names
.Length
);
203 for (int i
= 0; i
< info
.names
.Length
; ++i
)
204 info
.name_hash
[info
.names
[i
]] = i
;
206 MonoEnumInfo cached
= new MonoEnumInfo (info
);
207 lock (global_cache_monitor
) {
208 global_cache
[enumType
] = cached
;
215 public abstract class Enum
: ValueType
, IComparable
, IConvertible
, IFormattable
221 // IConvertible methods Start -->
222 public TypeCode
GetTypeCode ()
224 return Type
.GetTypeCode (GetUnderlyingType (this.GetType ()));
227 bool IConvertible
.ToBoolean (IFormatProvider provider
)
229 return Convert
.ToBoolean (Value
, provider
);
232 byte IConvertible
.ToByte (IFormatProvider provider
)
234 return Convert
.ToByte (Value
, provider
);
237 char IConvertible
.ToChar (IFormatProvider provider
)
239 return Convert
.ToChar (Value
, provider
);
242 DateTime IConvertible
.ToDateTime (IFormatProvider provider
)
244 return Convert
.ToDateTime (Value
, provider
);
247 decimal IConvertible
.ToDecimal (IFormatProvider provider
)
249 return Convert
.ToDecimal (Value
, provider
);
252 double IConvertible
.ToDouble (IFormatProvider provider
)
254 return Convert
.ToDouble (Value
, provider
);
257 short IConvertible
.ToInt16 (IFormatProvider provider
)
259 return Convert
.ToInt16 (Value
, provider
);
262 int IConvertible
.ToInt32 (IFormatProvider provider
)
264 return Convert
.ToInt32 (Value
, provider
);
267 long IConvertible
.ToInt64 (IFormatProvider provider
)
269 return Convert
.ToInt64 (Value
, provider
);
272 sbyte IConvertible
.ToSByte (IFormatProvider provider
)
274 return Convert
.ToSByte (Value
, provider
);
277 float IConvertible
.ToSingle (IFormatProvider provider
)
279 return Convert
.ToSingle (Value
, provider
);
282 object IConvertible
.ToType (Type targetType
, IFormatProvider provider
)
284 if (targetType
== null)
285 throw new ArgumentNullException ("targetType");
286 if (targetType
== typeof (string))
287 return ToString (provider
);
288 return Convert
.ToType (Value
, targetType
, provider
, false);
291 ushort IConvertible
.ToUInt16 (IFormatProvider provider
)
293 return Convert
.ToUInt16 (Value
, provider
);
296 uint IConvertible
.ToUInt32 (IFormatProvider provider
)
298 return Convert
.ToUInt32 (Value
, provider
);
301 ulong IConvertible
.ToUInt64 (IFormatProvider provider
)
303 return Convert
.ToUInt64 (Value
, provider
);
306 // <-- End IConvertible methods
308 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
309 private extern object get_value ();
311 // wrap the icall into a property so we don't hav to use the icall everywhere
312 private object Value
{
313 get { return get_value (); }
317 public static Array
GetValues (Type enumType
)
319 if (enumType
== null)
320 throw new ArgumentNullException ("enumType");
322 if (!enumType
.IsEnum
)
323 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
326 MonoEnumInfo
.GetInfo (enumType
, out info
);
327 return (Array
) info
.values
.Clone ();
331 public static string[] GetNames (Type enumType
)
333 if (enumType
== null)
334 throw new ArgumentNullException ("enumType");
336 if (!enumType
.IsEnum
)
337 throw new ArgumentException ("enumType is not an Enum type.");
340 MonoEnumInfo
.GetInfo (enumType
, out info
);
341 return (string []) info
.names
.Clone ();
345 // The faster, non-boxing version. It must use the special MonoEnumInfo.xxx_comparers
346 // to ensure that we are perfoming bitwise compares, and not signed compares.
348 // It also tries to use the non-boxing version of the various Array.BinarySearch methods
350 static int FindPosition (object value, Array values
)
352 int[] int_array
= values
as int[];
353 if (int_array
!= null)
354 return Array
.BinarySearch (int_array
, (int)value, MonoEnumInfo
.int_comparer
);
356 uint[] uint_array
= values
as uint [];
357 if (uint_array
!= null)
358 return Array
.BinarySearch (uint_array
, (uint)value);
360 short [] short_array
= values
as short [];
361 if (short_array
!= null)
362 return Array
.BinarySearch (short_array
, (short)value, MonoEnumInfo
.short_comparer
);
364 ushort [] ushort_array
= values
as ushort [];
365 if (ushort_array
!= null)
366 return Array
.BinarySearch (ushort_array
, (ushort)value);
368 sbyte [] sbyte_array
= values
as sbyte [];
369 if (sbyte_array
!= null)
370 return Array
.BinarySearch (sbyte_array
, (sbyte) value, MonoEnumInfo
.sbyte_comparer
);
372 byte [] byte_array
= values
as byte [];
373 if (byte_array
!= null)
374 return Array
.BinarySearch (byte_array
, (byte) value);
376 long [] long_array
= values
as long [];
377 if (long_array
!= null)
378 return Array
.BinarySearch (long_array
, (long) value, MonoEnumInfo
.long_comparer
);
380 ulong [] ulong_array
= values
as ulong [];
381 if (ulong_array
!= null)
382 return Array
.BinarySearch (ulong_array
, (ulong) value);
384 // This should never happen
385 return Array
.BinarySearch (values
, value);
389 public static string GetName (Type enumType
, object value)
391 if (enumType
== null)
392 throw new ArgumentNullException ("enumType");
394 throw new ArgumentNullException ("value");
396 if (!enumType
.IsEnum
)
397 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
400 value = ToObject (enumType
, value);
401 MonoEnumInfo
.GetInfo (enumType
, out info
);
403 int i
= FindPosition (value, info
.values
);
404 return (i
>= 0) ? info
.names
[i
] : null;
408 public static bool IsDefined (Type enumType
, object value)
410 if (enumType
== null)
411 throw new ArgumentNullException ("enumType");
413 throw new ArgumentNullException ("value");
415 if (!enumType
.IsEnum
)
416 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
419 MonoEnumInfo
.GetInfo (enumType
, out info
);
421 Type vType
= value.GetType ();
422 if (vType
== typeof(String
)) {
423 return ((IList
)(info
.names
)).Contains (value);
424 } else if ((vType
== info
.utype
) || (vType
== enumType
)) {
425 value = ToObject (enumType
, value);
426 MonoEnumInfo
.GetInfo (enumType
, out info
);
428 return FindPosition (value, info
.values
) >= 0;
430 throw new ArgumentException("The value parameter is not the correct type."
431 + "It must be type String or the same type as the underlying type"
436 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
437 private static extern Type
get_underlying_type (Type enumType
);
440 public static Type
GetUnderlyingType (Type enumType
)
442 if (enumType
== null)
443 throw new ArgumentNullException ("enumType");
445 if (!enumType
.IsEnum
)
446 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
448 return get_underlying_type (enumType
);
452 public static object Parse (Type enumType
, string value)
454 // Note: Parameters are checked in the other overload
455 return Parse (enumType
, value, false);
458 private static int FindName (Hashtable name_hash
, string [] names
, string name
, bool ignoreCase
)
461 /* For enums with many values, use a hash table */
462 if (name_hash
!= null) {
463 object val
= name_hash
[name
];
467 for (int i
= 0; i
< names
.Length
; ++i
) {
468 if (name
== names
[i
])
473 for (int i
= 0; i
< names
.Length
; ++i
) {
474 if (String
.Compare (name
, names
[i
], ignoreCase
, CultureInfo
.InvariantCulture
) == 0)
481 // Helper function for dealing with [Flags]-style enums.
482 private static ulong GetValue (object value, TypeCode typeCode
)
488 return (byte) ((sbyte) value);
490 return (ushort) ((short) value);
492 return (uint) ((int) value);
494 return (ulong) ((long) value);
495 case TypeCode
.UInt16
:
496 return (ushort) value;
497 case TypeCode
.UInt32
:
499 case TypeCode
.UInt64
:
500 return (ulong) value;
502 throw new ArgumentException ("typeCode is not a valid type code for an Enum");
505 private static char [] split_char
= { ',' }
;
508 public static object Parse (Type enumType
, string value, bool ignoreCase
)
510 if (enumType
== null)
511 throw new ArgumentNullException ("enumType");
514 throw new ArgumentNullException ("value");
516 if (!enumType
.IsEnum
)
517 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
519 value = value.Trim ();
520 if (value.Length
== 0)
521 throw new ArgumentException ("An empty string is not considered a valid value.");
524 if (!Parse (enumType
, value, ignoreCase
, out result
))
525 throw new ArgumentException (String
.Format ("The requested value '{0}' was not found.", value));
530 static bool Parse
<TEnum
> (Type enumType
, string value, bool ignoreCase
, out TEnum result
)
532 result
= default (TEnum
);
535 MonoEnumInfo
.GetInfo (enumType
, out info
);
537 // is 'value' a named constant?
538 int loc
= FindName (info
.name_hash
, info
.names
, value, ignoreCase
);
540 result
= (TEnum
) info
.values
.GetValue (loc
);
544 TypeCode typeCode
= ((Enum
) info
.values
.GetValue (0)).GetTypeCode ();
546 // is 'value' a list of named constants?
547 if (value.IndexOf (',') != -1) {
548 string [] names
= value.Split (split_char
);
550 for (int i
= 0; i
< names
.Length
; ++i
) {
551 loc
= FindName (info
.name_hash
, info
.names
, names
[i
].Trim (), ignoreCase
);
555 retVal
|= GetValue (info
.values
.GetValue (loc
), typeCode
);
557 result
= (TEnum
) ToObject (enumType
, retVal
);
561 // is 'value' a number?
565 if (!SByte
.TryParse (value, out sb
))
567 result
= (TEnum
) ToObject (enumType
, sb
);
571 if (!Byte
.TryParse (value, out b
))
573 result
= (TEnum
) ToObject (enumType
, b
);
577 if (!Int16
.TryParse (value, out i16
))
579 result
= (TEnum
) ToObject (enumType
, i16
);
581 case TypeCode
.UInt16
:
583 if (!UInt16
.TryParse (value, out u16
))
585 result
= (TEnum
) ToObject (enumType
, u16
);
589 if (!Int32
.TryParse (value, out i32
))
591 result
= (TEnum
) ToObject (enumType
, i32
);
593 case TypeCode
.UInt32
:
595 if (!UInt32
.TryParse (value, out u32
))
597 result
= (TEnum
) ToObject (enumType
, u32
);
601 if (!Int64
.TryParse (value, out i64
))
603 result
= (TEnum
) ToObject (enumType
, i64
);
605 case TypeCode
.UInt64
:
607 if (!UInt64
.TryParse (value, out u64
))
609 result
= (TEnum
) ToObject (enumType
, u64
);
618 #if BOOTSTRAP_NET_4_0 || NET_4_0 || MOONLIGHT
619 public static bool TryParse
<TEnum
> (string value, out TEnum result
) where TEnum
: struct
621 return TryParse (value, false, out result
);
624 public static bool TryParse
<TEnum
> (string value, bool ignoreCase
, out TEnum result
) where TEnum
: struct
626 Type tenum_type
= typeof (TEnum
);
627 result
= default (TEnum
);
629 if (value == null || value.Trim ().Length
== 0 || !tenum_type
.IsEnum
)
632 return Parse (tenum_type
, value, ignoreCase
, out result
);
636 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
637 private extern int compare_value_to (object other
);
640 /// Compares the enum value with another enum value of the same type.
644 public int CompareTo (object target
)
651 thisType
= this.GetType ();
652 if (target
.GetType() != thisType
) {
653 throw new ArgumentException (String
.Format (
654 "Object must be the same type as the enum. The type passed in was {0}; the enum type was {1}.",
655 target
.GetType(), thisType
));
658 return compare_value_to (target
);
661 public override string ToString ()
663 return ToString ("G");
666 [Obsolete("Provider is ignored, just use ToString")]
667 public string ToString (IFormatProvider provider
)
669 return ToString ("G", provider
);
672 public string ToString (String format
)
674 if (format
== String
.Empty
|| format
== null)
677 return Format (this.GetType (), this.Value
, format
);
680 [Obsolete("Provider is ignored, just use ToString")]
681 public string ToString (String format
, IFormatProvider provider
)
683 // provider is not used for Enums
685 if (format
== String
.Empty
|| format
== null) {
688 return Format (this.GetType(), this.Value
, format
);
692 public static object ToObject (Type enumType
, byte value)
694 return ToObject (enumType
, (object)value);
698 public static object ToObject (Type enumType
, short value)
700 return ToObject (enumType
, (object)value);
704 public static object ToObject (Type enumType
, int value)
706 return ToObject (enumType
, (object)value);
710 public static object ToObject (Type enumType
, long value)
712 return ToObject (enumType
, (object)value);
716 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
717 public static extern object ToObject (Type enumType
, object value);
720 [CLSCompliant (false)]
721 public static object ToObject (Type enumType
, sbyte value)
723 return ToObject (enumType
, (object)value);
727 [CLSCompliant (false)]
728 public static object ToObject (Type enumType
, ushort value)
730 return ToObject (enumType
, (object)value);
734 [CLSCompliant (false)]
735 public static object ToObject (Type enumType
, uint value)
737 return ToObject (enumType
, (object)value);
741 [CLSCompliant (false)]
742 public static object ToObject (Type enumType
, ulong value)
744 return ToObject (enumType
, (object)value);
747 public override bool Equals (object obj
)
749 return DefaultEquals (this, obj
);
752 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
753 private extern int get_hashcode ();
755 public override int GetHashCode ()
757 return get_hashcode ();
760 private static string FormatSpecifier_X (Type enumType
, object value, bool upper
)
762 switch (Type
.GetTypeCode (enumType
)) {
764 return ((sbyte)value).ToString (upper
? "X2" : "x2");
766 return ((byte)value).ToString (upper
? "X2" : "x2");
768 return ((short)value).ToString (upper
? "X4" : "x4");
769 case TypeCode
.UInt16
:
770 return ((ushort)value).ToString (upper
? "X4" : "x4");
772 return ((int)value).ToString (upper
? "X8" : "x8");
773 case TypeCode
.UInt32
:
774 return ((uint)value).ToString (upper
? "X8" : "x8");
776 return ((long)value).ToString (upper
? "X16" : "x16");
777 case TypeCode
.UInt64
:
778 return ((ulong)value).ToString (upper
? "X16" : "x16");
780 throw new Exception ("Invalid type code for enumeration.");
784 static string FormatFlags (Type enumType
, object value)
786 string retVal
= String
.Empty
;
788 MonoEnumInfo
.GetInfo (enumType
, out info
);
789 string asString
= value.ToString ();
790 if (asString
== "0") {
791 retVal
= GetName (enumType
, value);
796 // This is ugly, yes. We need to handle the different integer
797 // types for enums. If someone else has a better idea, be my guest.
798 switch (((Enum
)info
.values
.GetValue (0)).GetTypeCode ()) {
799 case TypeCode
.SByte
: {
800 sbyte flags
= (sbyte) value;
802 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
803 enumValue
= (sbyte) info
.values
.GetValue (i
);
807 if ((flags
& enumValue
) == enumValue
) {
808 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
812 if (flags
!= 0) return asString
;
815 case TypeCode
.Byte
: {
816 byte flags
= (byte) value;
818 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
819 enumValue
= (byte) info
.values
.GetValue (i
);
823 if ((flags
& enumValue
) == enumValue
) {
824 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
828 if (flags
!= 0) return asString
;
831 case TypeCode
.Int16
: {
832 short flags
= (short) value;
834 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
835 enumValue
= (short) info
.values
.GetValue (i
);
839 if ((flags
& enumValue
) == enumValue
) {
840 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
844 if (flags
!= 0) return asString
;
847 case TypeCode
.Int32
: {
848 int flags
= (int) value;
850 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
851 enumValue
= (int) info
.values
.GetValue (i
);
855 if ((flags
& enumValue
) == enumValue
) {
856 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
860 if (flags
!= 0) return asString
;
863 case TypeCode
.UInt16
: {
864 ushort flags
= (ushort) value;
866 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
867 enumValue
= (ushort) info
.values
.GetValue (i
);
871 if ((flags
& enumValue
) == enumValue
) {
872 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
876 if (flags
!= 0) return asString
;
879 case TypeCode
.UInt32
: {
880 uint flags
= (uint) value;
882 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
883 enumValue
= (uint) info
.values
.GetValue (i
);
887 if ((flags
& enumValue
) == enumValue
) {
888 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
892 if (flags
!= 0) return asString
;
895 case TypeCode
.Int64
: {
896 long flags
= (long) value;
898 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
899 enumValue
= (long) info
.values
.GetValue (i
);
903 if ((flags
& enumValue
) == enumValue
) {
904 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
908 if (flags
!= 0) return asString
;
911 case TypeCode
.UInt64
: {
912 ulong flags
= (ulong) value;
914 for (int i
= info
.values
.Length
- 1; i
>= 0; i
--) {
915 enumValue
= (ulong) info
.values
.GetValue (i
);
919 if ((flags
& enumValue
) == enumValue
) {
920 retVal
= info
.names
[i
] + (retVal
== String
.Empty
? String
.Empty
: ", ") + retVal
;
924 if (flags
!= 0) return asString
;
929 if (retVal
== String
.Empty
)
936 public static string Format (Type enumType
, object value, string format
)
938 if (enumType
== null)
939 throw new ArgumentNullException ("enumType");
941 throw new ArgumentNullException ("value");
943 throw new ArgumentNullException ("format");
945 if (!enumType
.IsEnum
)
946 throw new ArgumentException ("enumType is not an Enum type.", "enumType");
948 Type vType
= value.GetType();
949 Type underlyingType
= Enum
.GetUnderlyingType (enumType
);
951 if (vType
!= enumType
)
952 throw new ArgumentException (string.Format(CultureInfo
.InvariantCulture
,
953 "Object must be the same type as the enum. The type" +
954 " passed in was {0}; the enum type was {1}.",
955 vType
.FullName
, enumType
.FullName
));
956 } else if (vType
!= underlyingType
) {
957 throw new ArgumentException (string.Format (CultureInfo
.InvariantCulture
,
958 "Enum underlying type and the object must be the same type" +
959 " or object. Type passed in was {0}; the enum underlying" +
960 " type was {1}.", vType
.FullName
, underlyingType
.FullName
));
963 if (format
.Length
!= 1)
964 throw new FormatException ("Format String can be only \"G\",\"g\",\"X\"," +
965 "\"x\",\"F\",\"f\",\"D\" or \"d\".");
967 char formatChar
= format
[0];
969 if ((formatChar
== 'G' || formatChar
== 'g')) {
970 if (!enumType
.IsDefined (typeof(FlagsAttribute
), false)) {
971 retVal
= GetName (enumType
, value);
973 retVal
= value.ToString();
981 if ((formatChar
== 'f' || formatChar
== 'F'))
982 return FormatFlags (enumType
, value);
984 retVal
= String
.Empty
;
985 switch (formatChar
) {
987 retVal
= FormatSpecifier_X (enumType
, value, true);
990 retVal
= FormatSpecifier_X (enumType
, value, false);
994 if (underlyingType
== typeof (ulong)) {
995 ulong ulongValue
= Convert
.ToUInt64 (value);
996 retVal
= ulongValue
.ToString ();
998 long longValue
= Convert
.ToInt64 (value);
999 retVal
= longValue
.ToString ();
1003 throw new FormatException ("Format String can be only \"G\",\"g\",\"X\"," +
1004 "\"x\",\"F\",\"f\",\"D\" or \"d\".");
1008 #if NET_4_0 || MOONLIGHT
1009 public bool HasFlag (Enum flag
)
1011 ulong mvalue
= Convert
.ToUInt64 (get_value (), null);
1012 ulong fvalue
= Convert
.ToUInt64 (flag
, null);
1014 return ((mvalue
& fvalue
) == fvalue
);