Is this possible

  • Thread starter Thread starter Jack Robertson
  • Start date Start date
J

Jack Robertson

Hi there,

Is it possible to write the following function as a template where
"EnumFlags" becomes template parameter T (where T will always be an
enumerator with the "FlagsAttribute"). Nothing I've tried works, including
use of a "where" clause since T must always be of type "System.Enum". Thanks
in advance.

void SetFlag(EnumFlags Flag, ref EnumFlags Flags, bool On)
{
if (On)
{
Flags |= Flag;
}
else
{
Flags &= ~Flag;
}
}
 
A pain indeed... unfortunately AFAIK there is no easy route out;
generics doesn't support enums in this way... you could cast to the
underlying type, but then you make assumptions about the specific type
used (int, short, etc). Without treating as an int etc you can't use
the static binary operators...

Sorry,

Marc
 
Marc Gravell said:
A pain indeed... unfortunately AFAIK there is no easy route out;
generics doesn't support enums in this way... you could cast to the
underlying type, but then you make assumptions about the specific type
used (int, short, etc). Without treating as an int etc you can't use
the static binary operators...

Thanks for the confirmation. I didn't think so but casting is an ugly option
I wanted to avoid (notwithstanding the type issue). I'll think it's cleaner
to just replicate the same function over and over again as required (given
that I have little choice). Anyway, thanks again.
 
Something like the following should work. There still is casting
involved when calling the method, but you can take advantage of
generics for the return value. So you wouldn't need the method for
every enum, just every integral type.


static T SwapEnumFlag<T>(int flags, int flag) where T : struct
{
Debug.Assert(typeof(T).IsEnum, "T must be an enum");
Debug.Assert(typeof(T).IsDefined(typeof(FlagsAttribute), false), "T
must have the System.FlagsAttribute applied to it.");

if ((flags & flag) == flag)
flags &= ~flag;
else
flags |= flag;

return (T)Enum.ToObject(typeof(T), flags);
}


FlaggedEnum flagged = FlaggedEnum.Red | FlaggedEnum.Blue;
Debug.WriteLine(flagged); // output: Red, Blue

flagged = SwapEnumFlag<FlaggedEnum>((int)flagged,
(int)FlaggedEnum.Red);
Debug.WriteLine(flagged); // output: Blue

flagged = SwapEnumFlag<FlaggedEnum>((int)flagged,
(int)FlaggedEnum.Red);
Debug.WriteLine(flagged); // output: Red, Blue
 
Something like the following should work. There still is casting
involved when calling the method, but you can take advantage of
generics for the return value. So you wouldn't need the method for
every enum, just every integral type.


static T SwapEnumFlag<T>(int flags, int flag) where T : struct
{
Debug.Assert(typeof(T).IsEnum, "T must be an enum");
Debug.Assert(typeof(T).IsDefined(typeof(FlagsAttribute), false), "T
must have the System.FlagsAttribute applied to it.");

if ((flags & flag) == flag)
flags &= ~flag;
else
flags |= flag;

return (T)Enum.ToObject(typeof(T), flags);
}


FlaggedEnum flagged = FlaggedEnum.Red | FlaggedEnum.Blue;
Debug.WriteLine(flagged); // output: Red, Blue

flagged = SwapEnumFlag<FlaggedEnum>((int)flagged,
(int)FlaggedEnum.Red);
Debug.WriteLine(flagged); // output: Blue

flagged = SwapEnumFlag<FlaggedEnum>((int)flagged,
(int)FlaggedEnum.Red);
Debug.WriteLine(flagged); // output: Red, Blue

Thanks very much. Though I think casting is ugly and I normally try to avoid
it, I'll take a look at this in greater detail. I might use it as is or
leverage it in some way.Your effort is certainly appreciated. Thanks again.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top