Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anyone know a good workaround for the lack of an enum generic constraint?

Tags:

c#

.net

enums

flags

What I want to do is something like this: I have enums with combined flagged values.

public static class EnumExtension {     public static bool IsSet<T>( this T input, T matchTo )          where T:enum //the constraint I want that doesn't exist in C#3     {             return (input & matchTo) != 0;     } } 

So then I could do:

MyEnum tester = MyEnum.FlagA | MyEnum.FlagB  if( tester.IsSet( MyEnum.FlagA ) )     //act on flag a 

Unfortunately, C#'s generic where constraints have no enum restriction, only class and struct. C# doesn't see enums as structs (even though they are value types) so I can't add extension types like this.

Does anyone know a workaround?

like image 943
Keith Avatar asked Aug 10 '08 17:08

Keith


People also ask

Are enums bad practice?

Many people consider Enums as a code smell and an anti-pattern in OOPs. Certain books have also cited enums as a code smell, such as the following. In most cases, enums smell because it's frequently abused, but that doesn't mean that you have to avoid them. Enums can be a powerful tool in your arsenal if used properly.

Can enums be overridden?

You cannot override enums, and C# does not support return type covariance. You're going to have to find some other way; this is not possible.

Should enums have a default value?

Rule description. The default value of an uninitialized enumeration, just like other value types, is zero. A non-flags-attributed enumeration should define a member that has the value of zero so that the default value is a valid value of the enumeration.

Is enum a constraint?

Unless strict mode is disabled (not recommended, but see Section 5.1. 11, “Server SQL Modes”), the definition of a ENUM or SET column acts as a constraint on values entered into the column.


2 Answers

EDIT: This is now live in version 0.0.0.2 of UnconstrainedMelody.

(As requested on my blog post about enum constraints. I've included the basic facts below for the sake of a standalone answer.)

The best solution is to wait for me to include it in UnconstrainedMelody1. This is a library which takes C# code with "fake" constraints such as

where T : struct, IEnumConstraint 

and turns it into

where T : struct, System.Enum 

via a postbuild step.

It shouldn't be too hard to write IsSet... although catering for both Int64-based and UInt64-based flags could be the tricky part. (I smell some helper methods coming on, basically allowing me to treat any flags enum as if it had a base type of UInt64.)

What would you want the behaviour to be if you called

tester.IsSet(MyFlags.A | MyFlags.C) 

? Should it check that all the specified flags are set? That would be my expectation.

I'll try to do this on the way home tonight... I'm hoping to have a quick blitz on useful enum methods to get the library up to a usable standard quickly, then relax a bit.

EDIT: I'm not sure about IsSet as a name, by the way. Options:

  • Includes
  • Contains
  • HasFlag (or HasFlags)
  • IsSet (it's certainly an option)

Thoughts welcome. I'm sure it'll be a while before anything's set in stone anyway...


1 or submit it as a patch, of course...

like image 128
Jon Skeet Avatar answered Sep 19 '22 18:09

Jon Skeet


As of C# 7.3, there is now a built-in way to add enum constraints:

public class UsingEnum<T> where T : System.Enum { } 

source: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint

like image 37
Ivan Ferić Avatar answered Sep 19 '22 18:09

Ivan Ferić