Checking for unions between flags in C#
2020-06-12I spent a lot of time thinking this through yesterday and a lot of time today googling solutions, so I figured I’d write a short blog post about it in case it helps anyone else out.
Notes:
- This is in Unity C#, .Net 4+
- I could make this generic but I don’t need to right now. YAGNI.
Problem
- I have a large list of assets.
- I have a small number of slots those assets can fit into.
- Each asset and slot has a set of flags (a C# enum with the
flags
attribute).- These are flags so multiples can be set. Imagine the flags to be like
round, wide, tall, smooth, jagged, long, mutiple
.
- These are flags so multiples can be set. Imagine the flags to be like
- For an asset to be viable to fit into the slot, it must share at least 1 flag with the slot. Some slots accept multiple flags, like
round, smooth
while others only accept one.
Research
As mentioned, StackOverflow and Google were surprisingly little help on this. Most answers and pages took the route of iterating through the flags bit by bit and checking them in a loop, but I stumbled slightly on skipping ShapeTypes.None
. I knew that bitwise operators are often used with flags, but I couldn’t make it work in my head yesterday. Today it just sort of popped in there, probably owing to letting it rattle around my subconscious overnight. I was not in a good headstate yesterday for smart-people shit.
Solution
It turns out to be trivial to check for a union between flags using bitwise operations. You just take a
and it with b
to create c
. c
now contains only flags that were in both a
and b
. What I didn’t think of until today was casting c
to an int, and checking to see if it’s greater than 0. If it is, by definition, there were flags in the union. If c
is 0, then there were no flags in common.
Boom, done, no iteration, no hasflag()
.
public bool DoFlagsOverlap(ShapeTypes a, ShapeTypes b)
{
ShapeTypes c = a & b;
if ((int)c > 0)
{
return true;
}
else return false;
}
Kids stuff
I know, not a revelation. This, as far as I can remember in the deep past, is how most people use flags in Unity, but for some reason (possibly because I was searching for C# answers rather than Unity answers) I never found a similar solution, I had to construct it mentally myself, this time.
I don’t play around with bitwise operations much, obviously. I probably would have nailed this in a couple of minutes if I did. Maybe I should finally learn some C++, that might help me think of lower-level solutions occasionally.
I also realize now that I could probably one-line the return. Something like
return (int)c > 0 ? true : false;
but hey, it works.