Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is this possible

0 views
Skip to first unread message

Jack Robertson

unread,
Oct 20, 2006, 2:36:10 PM10/20/06
to
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;
}
}


Marc Gravell

unread,
Oct 20, 2006, 5:50:00 PM10/20/06
to
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

Jack Robertson

unread,
Oct 20, 2006, 6:04:40 PM10/20/06
to
"Marc Gravell" <marc.g...@gmail.com> wrote in message
news:1161381000.4...@b28g2000cwb.googlegroups.com...

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.


Bill Rodenbaugh

unread,
Oct 21, 2006, 12:59:31 AM10/21/06
to
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

Jack Robertson

unread,
Oct 23, 2006, 4:30:47 PM10/23/06
to
> 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.


0 new messages