2

I have the following enum

[Flags]
public enum WeekDays
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

In the UI, user can select ceratain days: Monday, Tuesday, Wednesday for example. The user selection of Monday, Tuesday, Wednesday is 7. This values is saved in the databse in a column called Days.

Now if I have a class:

public class Week
{
    public bool Monday { get; set; }
    public bool Tuesday { get; set; }
    public bool Wednesday { get; set; }
    public bool Thursday { get; set; }
    public bool Friday { get; set; }
    public bool Saturday { get; set; }
    public bool Sunday { get; set; }
}

How can I bind that value 7 and make the appropriate properties true or false. Example: 7 is equivalent for Monday, Tuesday, Wednesday enum. If I convert the value 7 to my class Week, the result will be properties: Monday, Tuesday, Wednesday are true, and the rest false.

If instead I have a class week where properties: Monday, Tuesday, Wednesday are true, and convert that into an enum WeekDays the result will be 7.

How can I do that?

user2818430
  • 5,853
  • 21
  • 82
  • 148

3 Answers3

2

One of the simplest ways is to check the flag using a bitwise-and (&) or using Enum.HasFlags(). I'll show both mixed:

Week Bind(WeekDays days)
{
    var w = new Week();
    w.Monday = (days & WeekDays.Monday) == WeekDays.Monday;
    w.Tuesday = days.HasFlag(WeekDays.Tuesday);
    w.Wednesday = (days & WeekDays.Wednesday) == WeekDays.Wednesday;
    w.Thursday = days.HasFlag(WeekDays.Thursday);
    w.Friday = (days & WeekDays.Friday) == WeekDays.Friday;
    w.Saturday = days.HasFlag(WeekDays.Saturday);
    w.Sunday = days.HasFlag(WeekDays.Sunday);

    return w;
}
Kit
  • 20,354
  • 4
  • 60
  • 103
  • 1
    Just a small thing - *unary* means an operator of one parameter. `&` is a *binary* operator because it takes 2 parameters. If you wish to distinguish between `&` and `&&`, then use *bitwise* and *logical*, respectively. Hope that makes sense. – kdbanman Jul 16 '15 at 21:53
  • Doh. It's late in the day and `&` seems less than `&&`. :) – Kit Jul 16 '15 at 21:56
1

You could make the Week have a property or field of type WeekDays that keeps track of which flags are active. And then all your boolean properties just check against that enum value, and on set update it correctly. This allows you to do this:

Week w = new Week();
w.Monday = true;
Console.WriteLine(w.Days); // Monday
w.Tuesday = true;
w.Wednesday = true;
Console.WriteLine(w.Days); // Monday, Tuesday, Wednesday

See the Week code is below, which is quite verbose (albeit introducing a SetDaysFlag helper method):

public class Week
{
    public WeekDays Days
    { get; set; }

    public bool Monday
    {
        get { return (Days & WeekDays.Monday) != 0; }
        set { SetDaysFlag(WeekDays.Monday, value); }
    }

    public bool Tuesday
    {
        get { return (Days & WeekDays.Tuesday) != 0; }
        set { SetDaysFlag(WeekDays.Tuesday, value); }
    }

    public bool Wednesday
    {
        get { return (Days & WeekDays.Wednesday) != 0; }
        set { SetDaysFlag(WeekDays.Wednesday, value); }
    }

    public bool Thursday
    {
        get { return (Days & WeekDays.Thursday) != 0; }
        set { SetDaysFlag(WeekDays.Thursday, value); }
    }

    public bool Friday
    {
        get { return (Days & WeekDays.Friday) != 0; }
        set { SetDaysFlag(WeekDays.Friday, value); }
    }

    public bool Saturday
    {
        get { return (Days & WeekDays.Saturday) != 0; }
        set { SetDaysFlag(WeekDays.Saturday, value); }
    }

    public bool Sunday
    {
        get { return (Days & WeekDays.Sunday) != 0; }
        set { SetDaysFlag(WeekDays.Sunday, value); }
    }

    /// <summary>
    /// Set or unset the flag on the <c>Days</c> property.
    /// </summary>
    /// <param name="flag">The flag to set or unset.</param>
    /// <param name="state">True when the flag should be set, or false when it should be removed.</param>
    private void SetDaysFlag (WeekDays flag, bool state)
    {
        if (state)
            Days |= flag;
        else
            Days &= ~flag;
    }
}
poke
  • 369,085
  • 72
  • 557
  • 602
  • Thanks! That's what I was looking for! – user2818430 Jul 16 '15 at 21:51
  • 1
    The `HasFlag` member of `Enum` is a real dog; if performance might possibly be an issue, testing `(Days & WeekDays.Thursday) != 0` will be well over an order of magnitude faster. If C# supported `enum` as a generic constraint, a generic method equivalent to `HasFlag` could be much more efficient. – supercat Jul 16 '15 at 22:22
  • @poke: Calling `Days.HasFlag(WeekDays.Friday)` will cause both `Days` and `WeekDays.Friday` to be converted to references of type `System.Enum`, which will entail creating new heap objects for each. Then the `Enum.HasFlag` method will need to get the type of each object, check them for compatibility, and extract the values from each before it can finally get around to doing a simple bitwise test. A generic method could reduce the overhead to a single delegate dispatch. And writing the code as a bitwise test will cause the compiler it to simply generate a simple bitwise test. – supercat Jul 16 '15 at 22:26
0
[Flags]
public enum WeekDays
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

public class Week
{

    public bool Monday { get; set; }
    public bool Tuesday { get; set; }
    public bool Wednesday { get; set; }
    public bool Thursday { get; set; }
    public bool Friday { get; set; }
    public bool Saturday { get; set; }
    public bool Sunday { get; set; }

    public static explicit operator WeekDays(Week week)
    {

        var points = new[]
        {
            week.Monday,
            week.Tuesday,
            week.Wednesday,
            week.Thursday,
            week.Friday,
            week.Saturday,
            week.Sunday
        };

        WeekDays weekDays = 0;

        for (var i = 0; i < points.Length; i++)
        {
            if (points[i])
            {
                weekDays = weekDays | (WeekDays)(1 << i);
            }
        }

        return weekDays;

    }

    public static explicit operator Week(WeekDays weekDays)
    {
        return new Week
        {
            Monday = weekDays.HasFlag(WeekDays.Monday),
            Tuesday = weekDays.HasFlag(WeekDays.Tuesday),
            Wednesday = weekDays.HasFlag(WeekDays.Wednesday),
            Thursday = weekDays.HasFlag(WeekDays.Thursday),
            Friday = weekDays.HasFlag(WeekDays.Friday),
            Saturday = weekDays.HasFlag(WeekDays.Saturday),
            Sunday = weekDays.HasFlag(WeekDays.Sunday)
        };
    }

    public override string ToString()
    {
        return String.Format("{0},{1},{2},{3},{4},{5},{6}", Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
    }
}
Ed Broome
  • 75
  • 6