locked
Using Flag Enums versus Is Properties RRS feed

  • Question

  • Where's that Krzyzstof fella when you need him?

     

    Does anyone have any interesting opinions on whether a class should use flag enums or boolean properties starting Is?

     

    Previously, I would have built my base classes with flag enums to indicate behavioural capabilities and state information but I've seen a significant trend towards properties such as IsNew, IsDirty, IsSealed etc.

     

    Maybe this is more Interface-friendly, and better for self-documentation. The base classes for controls in WPF are loaded with them!! Maybe they're for read-only state changes only, or possibly they lend themselves better to atomic operations.

     

    I considered frequency of use, but this would mean that common ones are separate from the others, which is ugly - although I could have them all exposed via enums and then shortcut just the common ones, but this doesn't sit right somehow.

     

    Should IsState properties only be used when;

     

     a) they are all valid as either true or false for any instance of the class/instances of derived types

     

     - The same could be said of flag enums, but I suppose its easier to override and throw the NotImplementedException in a derived type.

     

     b) none are mutually exclusive (they are all independant)?

     

     - What value does this add? It might be a good thing to catch an exception when trying to set IsClosed on an IsDirty object.

     

     

    Food for thought...

     

    Thanks for your time,

     

    Luke

    Wednesday, March 5, 2008 2:25 PM

Answers

  • Luke, I am here :-) I was out of office for a week.

     

    The Is properties are simply for usability reasons, and so I would not add them unless the API is very commonly used (APIs cost memory, resources, etc). They should be just simple shortcuts for "is flag X set" (which automatically meets your condition a). If these properties are get/set, then b definitely make the API clearer. For get only properties, b does not seem to be required. Is it?

     

    Tuesday, March 11, 2008 6:39 PM

All replies

  • Sorry to spam you by thinking aloud, but I can't find any discussions on the web about it so maybe someone will find this useful.

     

    The more I think about my classes, the more I'm thinking that enums are evil. They're evums.

     

    Originally, I was thinking of adding IsDirty and IsNew to my "Asset" base class, which I could have done with an enum, but the property is quick to code and easy to read.

     

    I then thought that I might have an "Asset" that isn't backed by some data layer - it exists only in the volatile process memory and is not persisted - so IsDirty would be meaningless.

     

    So my current design strips out these properties and leaves them for the derived-type to implement, or I might go through a PersistableAsset base which layers on these properties.

     

    Now I can extend and add more "switches" as they're needed which only apply where needed. Evums now appear to be very restrictive - but at some point I will have to ask myself how deep do I want my inheritence heirarchy?

     

    Luke

     

     

    Wednesday, March 5, 2008 3:13 PM
  • I am assuming that by flagEnums you are referring to using a bitmask type of design where you can simply say flag = IsDirty or IsNew. 

     

    With that assumption, I think that is a very efficient way to do things but I think that the standard is moving toward ease of use.  I think that for some developers the concept of bitmasking is difficult and confusing.  Especially when you try to explain why they should use OR.  So I think that the standard is to use Is properties for ease of use.

     

    As for the depth of inheritance, isn't that the million dollar question?  I remember taking a course on OOP many moons ago that we learned all the great features of OOP and how great inheritance is and then the instructor said "but be careful with it because too much of it can degrade performance".  I think that a lot of those issues have been resolved but it still is possible to overthink the inherited design of most systems and then it can become hard to use and maintain.

    Wednesday, March 5, 2008 8:43 PM
  • Our firm takes a specific two step approach to this decision.

     

    1) Are combinatorial checks meaningful? If the code is going to have to check multiple "aspects" to make a decision, the use of a Flag Enum can simplify code, and should be exposed.Even if combinatorial checks are probable, we still typically implement discrete boolean get/set properties.

     

    2) Is Memory or Performance the prime concern? If memory (ie there are going to be millions of instances) is overriding, then an IMPLEMENTATION of Flag Enum, with an exposure of Boolean Property makes sense. If Performance is the driving factor (typically ony for VERY real time environments), then the overhead of Splitting/Merging the flags may become significant and discrete boolean implementation may be required.

     

     

    Thursday, March 6, 2008 12:50 PM
  • I completely understand and agree with that approach David.  I think that you do have to make the decision based on your current scenario.  I simply think that ease of use has been the overriding priority for the standard approach that Microsoft and others have been following.  I think that both approaches have merit based on your needs.

    Thursday, March 6, 2008 1:24 PM
  • I'd say that Isxxxx is chosen for clarity.

     

    There's also a case to return a [flags] set of values, the problem being that you need to know that they're an enumeration marked [flags] to use it, whereas the Isxxxx is more obvious in it's function, although could be somewhat verbose.

     

    Personally I have used both, and would generally use Isxxxx unless there's a reason to use the flags approach, and I'd probably be more likely to use flags internally, and extenal interfaces be more clearly defined with Isxxxx...

     

    I hope this helps,

     

    Martin Platt.

    Friday, March 7, 2008 12:39 AM
  •  

    Hello

     

    Apologies for going quiet there, I was working from home and I have that “You have been logged off” error (and I’m too lazy to clean my cookies).

     

    So the following could sum up our thoughts;

     

    1. There isn’t any established guidance on this that I have missed.
    2. IsXxxx promotes a clearer interface.
    3. IsXxxx properties can be extended easily in derived types and appear naturally alongside its inherited members.
    4. Check if you anticipate having combined flags that indicate specific object states (pref checked in one operation) – For a rough example, a scenario where (IsReadable = true, IsWriteable = true, IsDeleteable = false) could be shortcut with enums using a bitmask called something like ModifiableFlag* which has the R and W bits set.
    5. Memory vs Performance is a factor where hypothetically, Boolean operations are faster than ANDing integers.
    6. If you do use publicly exposed flags, make the fact that they have bit semantics obvious**.

     

    *I don’t know what FxCop has to say about my use of this noun.

    **I’ve previously in my COM object models written little wrapper types that provide more understandable methods such as .AddFlag() .RemoveFlag() .IsFlagSet() .IsAnyFlagSet() .ClearFlags() and .ValueBehind

     

    If anyone has more to add, or wants to disparage this summary entirely, then feel free.

     

    Thanks to all for taking the time to consider my dilemma,

     

    Luke

    Friday, March 7, 2008 2:48 PM
  • Luke, I am here :-) I was out of office for a week.

     

    The Is properties are simply for usability reasons, and so I would not add them unless the API is very commonly used (APIs cost memory, resources, etc). They should be just simple shortcuts for "is flag X set" (which automatically meets your condition a). If these properties are get/set, then b definitely make the API clearer. For get only properties, b does not seem to be required. Is it?

     

    Tuesday, March 11, 2008 6:39 PM
  •  

    Krzyzstof, you must have bionic ears! Wink

     

    In my case, the properties are for use on classes in a framework (rather than in the guts of an application) which can be used for a multitude of applications, representing core business entities that we deal with each day, and often used by less experienced developers - so usability is my aim.

     

    The proposed properties are get-only so publicly handling mutually exclusive flags in a useable way is not a problem. I must admit, there's something about the word "is" which subtly implies read-only - one is only asking the question of something that has knowledge. Does anyone else feel that Is implies a publicly get-only property?

     

    I've a good mind to step into MS code in VS 2008 and take a look at some actual implementations.

     

    Many thanks,

     

    Luke

    Wednesday, March 12, 2008 12:02 PM

  • Ja nie jestem taki znany to moge sobie uzywac Andrzej na forums, ale ty powinnienes zmienic imie tu na Mr. K albo cos takiego.
    Wednesday, March 12, 2008 3:40 PM
  • Andy said [translating loosely]:

     

    "I am not as well known, so I can use my Polish name ‘Andrzej’ at various forums. You should use a pseudonym, something like ‘Mr. K’”

     

    But then people would stop writing to me in Polish, which I enjoy :-)

     

    Though, I have to admit ‘Mr. K’ sounds cool. If I switch my career to music, I will definitely consider :-)

     

    -krzys

     

    Monday, March 17, 2008 4:48 PM
  • For me bit flags are old school when memory footprint was king. Although I empathize with the worry you'll bloat your code with loads of properties this is easily rectified through using good development IDEs. The advantages of using properties for me are (that I don't think have been mentioned);
    1. Easy to locate when using an API from intellisense. IMO it is easier to look for something in plain language than to try and understand the name of a flag that represents a number of alternatives
    2. Diagnostics. As you mention when talking about checking that something has been set or not you can log that specific values have been set, you can put breakpoints on specific properties, etc.
    3. Easy to search for. Typically objects are persisted somewhere, be it a database, and XML file or object net. Asking questions on a set of objects using enums feels...clumbsy. Also different stores use different bit wise operators that just serves to add another point of failure.

    Having said all that, I wouldn't fail a review that used flags however I frown upon passing Booleans as arguments. E.g.which is the easier to predict the behaviour of between; Call Authenticate(User, true)...or Call Authenticate(User, AuthenticateBehavior.RaiseExceptionIfFailed). I mention that because if you consider a constructor for the property based class you could end up wth a lot of 'true,false,false' inputs which I wouldn't want to see.

    There you go my recommendation is clear Wink





    Thursday, March 20, 2008 7:11 AM
  • As cumbersome as it seems, this can only be your decision. You can use whichever you feel more comfortble with.
    For example, If you have a property that can hold multiple values that somehow have the same meaning you might want to use Flags. If you don't like using flags you could use properties, or you could use a mix of both:

    Code Snippet - Example
    [flags]
    enum FlagProp
    {
    flag1,
    flag2
    }

    class Flagged
    {
    private FlagProp properties;

    public bool IsFlag1
    {
    get { return properties & FlagProp.flag1}
    }

    public bool IsFlag2
    {
    get { return properties & FlagProp.flag2}
    }

    public FlagProp FlagProperties
    {
    return properties;
    }
    }


    Normally, I would choose an internal implementation with flags and a public interface without flags (just the bool properties), as it would have a more natural meaning to access a property like IsNew or IsSealed instead of having to do
    bit operations each time a caller wants to check if the object has one flag.

    An advantage for flags is that if you have a lot of options would reduce the code that you have to write (for example just the enum containing 10 flags and 1 property compared to 10 bool properties).

    One disadvantage would be that if you want to respond to the "switch" of a specific flag, your setter code would get more "ciclomatic complexity".
    Wednesday, March 26, 2008 10:39 AM