rboy
rboy

Reputation: 2165

Looping around in Enumeration in C#

Is there some way to automatically loopback when the value of an Enumeration reaches the end while adding or subtracting values.

E.g. When using DateTime.DayOfWeek it is defined as:

public enum DayOfWeek
{
    Sunday = 0,
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
}

I have a function where I'm checking if a string array contains yesterday.

DateTime rn = DateTime.Now;
string[] daysOfWeek = {"Monday", "Tuesday", "Saturday"};
if (daysOfWeek.Contains((rn.DayOfWeek - 1).ToString()))
    ...

If today is Sunday. Is there some way to make the rn.DayOfWeek enumeration to loop back around the beginning to Saturday in this case? Similarly if I'm adding instead of subtracting, can one somehow loop around the end from Saturday (6) back to Sunday (0)?

Upvotes: 0

Views: 398

Answers (5)

Grozz
Grozz

Reputation: 8425

You can create a following extension method (can easily be changed for string arrays).

public static bool ContainsYesterday(this DayOfWeek[] days)
{
    return days.Contains(DateTime.Now.AddDays(-1).DayOfWeek);
}

edited as previous version had a bug specified in comment.

Upvotes: 0

GoldenCrystal
GoldenCrystal

Reputation: 83

You cannot have an automatic "looping" behavior on random enumerations, however, there are some ways you could handle your problem.

Most of the time, you could simply use the % operator, which in the case of DayOfWeek would amount to something like this:

// Prints Friday
Console.WriteLine((DayOfWeek)(((int)DayOfWeek.Saturday + 6) % 7));

You could also write an extension method like this one:

public static class DateTimeExtensions
{
    public static DayOfWeek AddDays(this DayOfWeek dayOfWeek, int count)
    {
        if (dayOfWeek < 0 || (int)dayOfWeek > 6) throw new ArgumentOutOfRangeException();

        int adjustedValue = ((int)dayOfWeek + count) % 7;

        return (DayOfWeek)(adjustedValue < 0 ? adjustedValue + 7 : adjustedValue);
    }
}

With this extension method, you could do something like this:

Console.WriteLine(DayOfWeek.Sunday.AddDays(-1)); // Prints "Saturday"
Console.WriteLine(DayOfWeek.Sunday.AddDays(1)); // Prints "Monday"
Console.WriteLine(DayOfWeek.Sunday.AddDays(7)); // Prints "Sunday"
Console.WriteLine(DayOfWeek.Sunday.AddDays(-7)); // Prints "Sunday"

Upvotes: 1

Ronan Thibaudau
Ronan Thibaudau

Reputation: 3603

There's no built in way to do this but if you're happy working with integers then it's pretty easy, you just want to remap all your values from -X to +X into the 0-6 range so for a positive value you'd do

value+1 (to remap to 1-7 range since we're going to divide by 7) %7 (this gives you the remainder of the division by 7, so 1%7 = 1 8 = 1 etc etc, you've got it looping every 7 days) -1 (to remap out 1-7 range to your 0-6 enum value) and cast that as your enum.

Now we just need to consider negative value and convert the negative value into something positive first before passing it into our previous function. In this case we want to map the oposite days (-1 is the same as +6, one day before the start of the week is 6 days after the end of the week etc), so if your value is negative you want to do abs(value) to make it positive and the substract it from 7 to remap it into the positive range

Here's some code (untested)

if(value < 0)
{
    value = 7 - Math.Abs(value)
}

value++; (remap 0-6 to 1-7)
value = value % 7; (remap 1 - int.maxvalue to 1-7)
value--; (remap 1-7 to 0-6;

And now value contains the number that maps to your enum.

Upvotes: 0

Kapol
Kapol

Reputation: 6463

I guess in this particular case it could be

DateTime rn = DateTime.Now.AddDays(5);
string[] daysOfWeek = { "Monday", "Tuesday", "Saturday" };
if (daysOfWeek.Contains(((rn.DayOfWeek) == 0 ? rn.DayOfWeek + 6 : rn.DayOfWeek - 1).ToString()))
    Console.WriteLine("Found");

Although I agree that such code generally should not be used.

Upvotes: 1

itsme86
itsme86

Reputation: 19496

You shouldn't be adding/subtracting when dealing with enums. That is dangerous ground. Instead, you should be adding/subtracting days to your DateTime:

string today = DateTime.Now.DayOfWeek.ToString();
string tomorrow = DateTime.Now.AddDays(1).DayOfWeek.ToString();
string yesterday = DateTime.Now.AddDays(-1).DayOfWeek.ToString();

Upvotes: 4

Related Questions