c# - Display Possible Flags or modify to accommodate to existing flags -


i have piece of code enum flags api. when api changes , updates, might values not defined in enum structure.

example:

[flags] public enum testenum {    enum1 = 1,    enum2 = 2,    enum3 = 4 } 

when (testenum)7, get, string representation when outputting said data, "enum1|enum2|enum3". however, if api changes, , gives me additional flag "8" set (testenum)15, string representation, in visual studio, not give me flags, display "0xf"

is there way either bits mapped displayed, or in example, "forget" enum4, forth bit. there way this?

what have mask value combination of defined values , "tostring()" on that, , mask value compliment of defined values , tostring() on remainder:

    testenum value = (testenum)(64 - 1);     var = ((testenum[])enum.getvalues(typeof(testenum))).aggregate((testenum)0, (a, c) => | c);     var str = (value & all).tostring() + ((value & ~all) == 0 ? "" : ", 0x" + (value & ~all).tostring("x"));     debug.writeline(str); 

and output is

    enum1, enum2, enum3, 0x00000038 

doing generic extension method weirdly hard, because there's no generic enum constraint in c#, , no way bitmasking directly in generic method targetted @ enums. here's 1 attempt:

public static class enumhelper {     // generic singleton remembering basic properties specified enums, cached performance.     sealed class datasingleton<tenum> tenum : struct, iconvertible, icomparable, iformattable     {         static readonly datasingleton<tenum> instance = new datasingleton<tenum>();          readonly bool issigned;         readonly tenum allvalues;         readonly bool hasflags;         readonly bool isenum;          // explicit static constructor tell c# compiler         // not mark type beforefieldinit         static datasingleton()         {         }          datasingleton()         {             var type = typeof(tenum);             isenum = type.isenum;             if (isenum)             {                 issigned = getissigned();                 allvalues = getall();                 hasflags = gethasflags();             }             else             {                 issigned = false;                 allvalues = default(tenum);                 hasflags = false;             }         }          static bool gethasflags()         {             var attributes = typeof(tenum).getcustomattributes(typeof(flagsattribute), false);             return attributes != null && attributes.length > 0;         }          static bool getissigned()         {             var underlyingtype = enum.getunderlyingtype(typeof(tenum));             bool issigned = (underlyingtype == typeof(long) || underlyingtype == typeof(int) || underlyingtype == typeof(short) || underlyingtype == typeof(sbyte));             bool isunsigned = (underlyingtype == typeof(ulong) || underlyingtype == typeof(uint) || underlyingtype == typeof(ushort) || underlyingtype == typeof(byte));             if (!issigned && !isunsigned)                 throw new invalidoperationexception();             return issigned;         }          static tenum getall()         {             if (getissigned())             {                 long value = 0;                 foreach (var v in enum.getvalues(typeof(tenum)))                     // not sure need culture microsoft passes in enum.touint64(object value) - http://referencesource.microsoft.com/#mscorlib/system/enum.cs                     value |= convert.toint64(v, cultureinfo.invariantculture);                 return (tenum)enum.toobject(typeof(tenum), value);             }             else             {                 ulong value = 0;                 foreach (var v in enum.getvalues(typeof(tenum)))                     // not sure need culture microsoft passes in enum.touint64(object value) - http://referencesource.microsoft.com/#mscorlib/system/enum.cs                     value |= convert.touint64(v, cultureinfo.invariantculture);                 return (tenum)enum.toobject(typeof(tenum), value);             }         }          public bool hasflags { { return hasflags; } }          public bool issigned { { return issigned; } }          public tenum allvalues { { return allvalues; } }          public bool isenum { { return isenum; } }          public static datasingleton<tenum> instance { { return instance; } }     }      private static void throwonnonenum<tenum>(datasingleton<tenum> data) tenum : struct, iconvertible, icomparable, iformattable     {         if (!data.isenum)         {             throw (new argumentexception("the generic argument [<tenum>] must enumeration.", "tenum: " + typeof(tenum).fullname));         }     }      private static void throwonenumwithflags<tenum>(datasingleton<tenum> data) tenum : struct, iconvertible, icomparable, iformattable     {         if (!data.isenum || data.hasflags)         {             throw (new argumentexception("the generic argument [<tenum>] must enumeration without [flagsattribute] applied.", "tenum: " + typeof(tenum).fullname));         }     }      private static void throwonenumwithoutflags<tenum>(datasingleton<tenum> data) tenum : struct, iconvertible, icomparable, iformattable     {         if (!data.isenum || !data.hasflags)         {             throw (new argumentexception("the generic argument [<tenum>] must enumeration [flagsattribute] applied.", "tenum: " + typeof(tenum).fullname));         }     }      public static tenum getall<tenum>() tenum : struct, iconvertible, icomparable, iformattable     {         var data = datasingleton<tenum>.instance;         throwonenumwithoutflags<tenum>(data);         return data.allvalues;     }      static ulong touint64<tenum>(tenum value) tenum : struct, iconvertible, icomparable, iformattable     {         // silently convert value uint64 other base          // types enum without throwing exception.         // need since convert functions overflow checks.         typecode typecode = value.gettypecode();         ulong result;          switch (typecode)         {             case typecode.sbyte:             case typecode.int16:             case typecode.int32:             case typecode.int64:                 unchecked                 {                     result = (uint64)value.toint64(cultureinfo.invariantculture);                 }                 break;              case typecode.byte:             case typecode.uint16:             case typecode.uint32:             case typecode.uint64:             case typecode.boolean:             case typecode.char:                 unchecked                 {                     result = value.touint64(cultureinfo.invariantculture);                 }                 break;              default:                 throw new invalidoperationexception();         }         return result;     }      public static string todebugstring<tenum>(this tenum anenum) tenum : struct, iconvertible, icomparable, iformattable     {         var data = datasingleton<tenum>.instance;         if (!data.isenum || !data.hasflags)             return anenum.tostring();         var alllong = touint64(data.allvalues);         var enumlong = touint64(anenum);         string str1 = ((tenum)enum.toobject(typeof(tenum), enumlong & alllong)).tostring(cultureinfo.invariantculture);         var compliment = enumlong & ~(alllong);         if (compliment == 0)             return str1;         return str1 + ", 0x" + ((tenum)enum.toobject(typeof(tenum), compliment)).tostring("x", cultureinfo.invariantculture);     } } 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

thorough guide for profiling racket code -