8
\$\begingroup\$

I have this code, but it looks a bit verbose:

enum MonitoringMode
{
    Seek,
    Destroy
}
void ToggleMonitoringMode()
{
    if (_monitoringMode == MonitoringMode.Seek)
        _monitoringMode = MonitoringMode.Destroy;
    else
    if (_monitoringMode == MonitoringMode.Destroy)
        _monitoringMode = MonitoringMode.Seek;
}

There are some well known idioms to toggle between two values, like:

bitwiseBoolean ^= bitwiseBoolean; // bit toggle
boolean = !boolean;               // boolean toggle
oneOrZero = 1 - oneOrZero;        // numeric toggle

Is there a similar, less verbose way to get the same result? I am not sure using the int value of enums would be safe or even "elegant" in C#.

\$\endgroup\$
5
  • 4
    \$\begingroup\$ If your enum only has two values, you don't have an enum, you have a bool. \$\endgroup\$
    – Kevin
    Aug 26, 2015 at 21:09
  • \$\begingroup\$ @Kevin technicaly speaking it's true but to make the meaning of true/false more verbose I also prefer to use enums in many situations. \$\endgroup\$
    – t3chb0t
    Aug 27, 2015 at 19:32
  • \$\begingroup\$ then you are making toggling a lot harder than it has to be. bool InDestroyMode =true; InDestroyMode = !InDestroyMode is a lot simpler than the accepted answer. \$\endgroup\$
    – Kevin
    Aug 27, 2015 at 20:01
  • 1
    \$\begingroup\$ @Kevin pasting my comment on moarboilerplate's answer: I thought about using boolean, but boolean has an "apple vs non-apple" semantics, while I prefer (or actually, the application requires) an "apple vs orange (vs not-yet-considered fruit)" semantics. \$\endgroup\$ Aug 27, 2015 at 20:30
  • \$\begingroup\$ Yes, if you know there are going to be further options later, then boolean is not the way to go \$\endgroup\$
    – Kevin
    Aug 27, 2015 at 20:42

2 Answers 2

12
\$\begingroup\$

Would there ever be a need to add more values to the MonitoringMode enum?

enum MonitoringMode
{
    Seek,
    Destroy,
    Something,
    SomethingElse
}

In that case, you're not "toggling" - you're mapping. And there's a data structure for that:

private static readonly IDictionary ModeMap = new Dictionary<MonitoringMode,MonitoringMode>
{
    { MonitoringMode.Seek, MonitoringMode.Destroy },
    { MonitoringMode.Destroy, MonitoringMode.Seek },
    // ...
};

Then you could switch from one value to the next simply by using that map:

void ToggleMonitoringMode()
{
    _monitoringMode = ModeMap[_monitoringMode];
}

If there's not going to be a need to ever add more values, then I'd question the use of an enum type here, because you're really toggling between true and false states of some _isSeeking Boolean, which you already know how to toggle.

\$\endgroup\$
10
  • \$\begingroup\$ You're right. I must say I have two modes NOW but they are not intrinsically binary (that is, I can see a lot of future reasons demanding additional modes). I'll wait a little bit before accepting, but this is a very interesting solution indeed! Thanks for now! \$\endgroup\$ Aug 26, 2015 at 18:42
  • 3
    \$\begingroup\$ Picking on Mr. Mug a bit here, mapping based on a dictionary turns all of your rules that could be expressed statically in code and unit tested individually into items that are evaluated at runtime, which could be an issue. Especially if diagnosing problems requires peeking into said collection using a debugger \$\endgroup\$ Aug 26, 2015 at 20:56
  • \$\begingroup\$ @moarboilerplate fair point. How about making ModeMap public then, and have unit tests that validate the mappings? ...or better - constructor-injected as IDictionary<MonitoringMode,MonitoringMode> mappingRules? \$\endgroup\$ Aug 26, 2015 at 21:00
  • \$\begingroup\$ That would work provided the values in your dictionary are all value types or expressions. But it all hinges on the question of why a mapping rule should be stored as a representation of itself and not explicitly coded instructions. If the answer is "developer convenience" that may be problematic. \$\endgroup\$ Aug 26, 2015 at 21:13
  • 2
    \$\begingroup\$ You'd think so, but the things I've seen, man. \$\endgroup\$ Aug 26, 2015 at 21:24
2
\$\begingroup\$

If you are into bit-twiddling, you can have your cake and eat it too with the [Flags] attribute. However, I would only use this when you want to represent combinations of more than one value, you want to execute conditionals based on these values, and/or your zeroth value has significant meaning (but I'd still use a bool for simplicity over a 2-item enum).

\$\endgroup\$
2
  • 1
    \$\begingroup\$ That's a good option (the Flags attribute). I thought about using boolean, but boolean has a "apple vs non-apple" semantics, while I prefer (or actually, the application deserves) an "apple vs orange" semantics. \$\endgroup\$ Aug 26, 2015 at 22:00
  • 1
    \$\begingroup\$ I would really only use the flags if your values are additive qualities. So apple would not be Apple, it would be GrowsOnTree | IsRed (terrible example, I've never thought so hard about how to classify an apple). Maybe what you're really after is the concept of a discriminated union? \$\endgroup\$ Aug 26, 2015 at 22:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.