tags:

views:

130

answers:

3

So, I just hate using true/false as method arguments for "enabled"/"disabled". To freely quote Jeff: "I dislike it on a fundamental level".

I repeatedly find myself defining my own enums on every new project in different namespaces all over the place, like these:

public enum Clickability
{
    Disabled,
    Enabled
}

public enum Editability
{
    Disabled,
    Enabled
}

public enum Serializability
{
    Disabled,
    Enabled
}

Is there a generic enum I can use for these scenarios?

A: 

No, there is no such enum in the BCL (to the best of my knowledge). But it's not hard to take one of those that you repeatedly create and make it more general:

public enum Ability
{
    Disabled,
    Enabled
}

Stick it into some class library with similarly general stuff, and reuse it in your projects.

Fredrik Mörk
+7  A: 

The problem with this is that it doesn't actually help in the real problematic cases which is when there are multiple arguments and it is not clear what the 'flag' is controlling.

If you follow the rule that you should 'avoid double negatives' then simple single booleans are fine:

public static void Foo(bool useBaz)

public static void Foo(Ability useBaz)

Then Foo(true), verses Foo(Ability.Enabled) and Foo(false), verses Foo(Ability.Disabled) are really pretty obvious to most.

However when you hit a method like:

public static void Foo(
    bool useBaz, 
    bool barIsHigh, 
    bool useFlibble, 
    bool ignoreCase)

then it matters not whether you use booleans or general enums they still both end up looking like this at the call site:

Foo(false,true,false,false);
Foo(Ability.Enabled,Ability.Enabled,Ability.Disabled,Ability.Enabled);

Neither is pretty.

Using specific enumerations for the case in hand:

enum BarOption { Off, On }
enum BazConsidered { Low, High }
enum FlibbleOption { Off,  On  }
// for case sensitivity use System.StringComparison

then you get

Foo(Bar.On,
    BazConsidered.Low,
    FlibbleOption.On,
    StringComparison.IgnoreCase );

or, if all are simple boolean states and likely to remain so then using a Flagged enumeration better still.

[Flags]
enum FooOptions
{
    None = 0,
    UseBaz = 1,
    BazConsideredHigh = 2,
    UseFlibble = 4,
}

Then you would have:

Foo(FooOptions.UseBar | FooOptions.UseFlibble, StringComparison.IgnoreCase);

Appropriate selection of the 'active' flags so that you specify only what is uncommon will then lead to highlighting 'uncommon' usages.

ShuggyCoUk
+1. The specific enums give you also some type-safety. You don't enable something accidentally because you missed the correct order of arguments.
Stefan Steinegger
Thanks. I think I'll stick with my specific enums, e.g., Clickability, Editability, Serializability, because they offer superior readability at the call site.
Johann Gerell
A: 

What's wrong with using bool parameters with meaningful names?

public void Foo(bool clickabilityEnabled, bool editabilityEnabled) { ... }

Or, better still, something a bit less verbose:

public void Bar(bool isClickable, bool isEditable, bool isSerializable) { ... }

public void Baz(bool canClick, bool canEdit, bool canSerialize) { ... }

I would find this much more readable than loads of enum parameters.

LukeH
The method definitions might be readable but what do the invocations looks like?
AakashM
@AakashM: In my opinion the call site will also be more readable than if we used a "generic" enum like the OP is requesting: `Foo(true, false, true);` versus `Foo(GenericEnum.Enabled, GenericEnum.Disabled, GenericEnum.Enabled);`
LukeH
@Luke (What's wrong with using bool parameters with meaningful names?): Well, specific enums, e.g., Clickability, Editability, Serializability, offer superior readability (as in self documenting) at the call site for anyone reading the code without the need to jump to the method definition to see what each Boolean does or mean.
Johann Gerell
@Johann: I agree that specific enums *might* give better readability, but your question asks about replacing those specific enums with a single "generic" enum, which would give poorer readability than using well-named boolean parameters.
LukeH
@Luke: You are correct. My actual requirement crystalized after asking this question in the first place. It wasn't until then I realized that I really wanted the specific enums that I'm always defining.
Johann Gerell