-1

Here's the code I'm working on (I found some of it online) and I'm trying to return a List<> of the flags that are active. Here's the code:

public static class BitMask {
        public static bool IsSet<T>(T flags, T flag) where T : struct {
            int flagsValue = (int)(object)flags;
            int flagValue = (int)(object)flag;

            return (flagsValue & flagValue) != 0;
        }

        public static void Set<T>(ref T flags, T flag) where T : struct {
            int flagsValue = (int)(object)flags;
            int flagValue = (int)(object)flag;

            flags = (T)(object)(flagsValue | flagValue);
        }

        public static void Unset<T>(ref T flags, T flag) where T : struct {
            int flagsValue = (int)(object)flags;
            int flagValue = (int)(object)flag;

            flags = (T)(object)(flagsValue & (~flagValue));
        }

        public static List<T> GetActiveMasks<T>(ref T flags) where T : struct {
            List<T> returned = new List<T>();
            foreach(T value in flags) 
                if(IsSet(flags, value))
                    returned.Add(value);

            return returned;
        }
    }

However, I'm running into this issue:

foreach statement cannot operate on variables of type 'T' because 'T' does not contain a public definition for 'GetEnumerator' (CS1579) - C:\Users\Christian\Documents\SharpDevelop Projects\OblivionScripts\OblivionScripts\Common\BitMask.cs:36,4

Could someone please nudge me in the right direction as I'm still new to C#.

Hobbyist
  • 15,888
  • 9
  • 46
  • 98
  • 1
    This may help: http://stackoverflow.com/questions/105372/enumerate-an-enum – BJ Myers May 06 '15 at 21:43
  • enums can be long or unlong, not just int. – dbc May 06 '15 at 21:49
  • 1
    Your code is a very strange way to make this kind of thing generic. If you choose this path anway, use `ulong` to support larger primitives (right now, a 64-bit primitive will have its 32 most significant bits erased using this method) – Bas May 06 '15 at 21:50

4 Answers4

1

In your example, what is T going to be replaced with? Is this supposed to work with an enum that has the [Flags] attribute?

If so, then you should be able to get the code to work by writing your method like this:

    public static List<T> GetActiveMasks<T>(ref T flags) where T : struct {
        List<T> returned = new List<T>();
        foreach(T value in Enum.GetValues(typeof(T)).Cast<T>()) 
            if(IsSet(flags, value))
                returned.Add(value);

        return returned;
    }

Now, that said: note that in many such enum scenarios, the enum type has not only individual flags, but aliases and/or combined flags. Your code will detect those as being "set" as well. There's not enough context in your question to know whether this would actually be a problem, never mind how to address it correctly. I simply mention it as a possible "gotcha", in case you weren't aware.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • 'System.Array' does not contain a definition for 'Cast' and no extension method 'Cast' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?) (CS1061) - C:\Users\Christian\Documents\SharpDevelop Projects\OblivionScripts\OblivionScripts\Common\BitMask.cs:36,49 – Hobbyist May 06 '15 at 21:56
  • You need to include `using System.Linq;` in your .cs file for the LINQ extensions (like `Cast()`) to work. That said, I include that only as a personal preference for clarity in the code; the `foreach` statement will implicitly cast (if possible) for you, so you could just omit that if you prefer. – Peter Duniho May 06 '15 at 22:10
0

flags needs to be some enumerable type, you probably meant:

  public static List<T> GetActiveMasks<T>(ref IEnumerable<T> flags) 
          where T : struct {
        ...
    }
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
0

The flags you pass in must be a collection of T, because T is a struct not a collection.

  public static List<T> GetActiveMasks<T>(ref IEnumerable<T> flags) where T : struct {
        List<T> returned = new List<T>();
        foreach(T value in flags) 
            if(IsSet(flags, value))
                returned.Add(value);

        return returned;
    }
adricadar
  • 9,971
  • 5
  • 33
  • 46
0

You can't iterate on a generic type. If the flags parameter were of type List<T> you'd be able to iterate on that.

public static List<T> GetActiveMasks<T>(ref List<T> flags) where T : struct 
TomSlick
  • 717
  • 5
  • 21