Mert
Mert

Reputation: 17

How to execute while loop given number of times?

I have this while loop to get next working day excluding holidays and sundays. But it calculates by adding 1 day. And i want that number of day to be given by the user. I get that input from the below TextBox (TboxIzin).

How can execute that while loop to do the calculation for given number of times?


         int i = 1;
         int sayi;
         IzinIslem i1 = new IzinIslem();
         int.TryParse(i1.TboxIzin.Text, out sayi);
            public static DateTime GetNextWeekDay(DateTime date, 
                 IList<Holiday> holidays, IList<DayOfWeek> weekendDays)
        {
            int i = 1;
            int sayi;
            IzinIslem i1 = new IzinIslem();
            int.TryParse(i1.TboxIzin.Text, out sayi);

            // always start with tomorrow, and truncate time to be safe
            date = date.Date.AddDays(1);

            // calculate holidays for both this year and next year
            var holidayDates = holidays.Select(x => x.GetDate(date.Year))
                .Union(holidays.Select(x => x.GetDate(date.Year + 1)))
                .Where(x => x != null)
                .Select(x => x.Value)
                .OrderBy(x => x).ToArray();

            // increment to get working day
            while (true)
            {
                if (weekendDays.Contains(date.DayOfWeek) || 
                          holidayDates.Contains(date))
                    date = date.AddDays(1);
                else
                    return date;
            }

        }

I get not all code paths return a value error when i try nesting while loops.

Upvotes: 1

Views: 248

Answers (3)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186698

Let's get rif of all UI in the GetNextWeekDay (like int.TryParse(i1.TboxIzin.Text, out sayi);):

public static DateTime GetNextWeekDay(DateTime date, 
                                      IEnumerable<Holiday> holidays, 
                                      IEnumerable<DayOfWeek> weekendDays) {

  // public method arguments validation
  if (null == holidays)
    throw new ArgumentNullException(nameof(holidays));
  else if (null == weekendDays)
    throw new ArgumentNullException(nameof(weekendDays));

  HashSet<DayOfWeek> wends = new HashSet<DayOfWeek>(weekendDays);

  // Current Year and Next years - .AddYear(1)
  HashSet<DateTime> hds = new HashSet<DateTime>(holidays
    .Select(item => item.Date)
    .Concate(holidays.Select(item => item.Date.AddYear(1))));  

  for (var day = date.Date.AddDays(1); ; day = day.AddDays(1)) 
    if (!wends.Contains(day.DayOfWeek) && ! hds.Contains(day))
      return day;
}

Or if you prefer Linq, the loop can be rewritten as

return Enumerable
  .Range(1, 1000)
  .Select(day => date.Date.AddDays(day))
  .TakeWhile(item => item.Year - date.Year <= 1)
  .First(item => !wends.Contains(item.DayOfWeek) && !hds.Contains(item));

Upvotes: 1

Guillaume CR
Guillaume CR

Reputation: 3016

while is a conditional loop. Here you put a non-condition in the clause and immediately follow up with a condition. Put the condition in the while clause:

while(weekendDays.Contains(date.DayOfWeek) || holidayDates.Contains(date)) {
    date = date.AddDays(1);
}

return date;

The actual reason you're getting the error is that the compiler cannot predict if your if condition will ever resolve to false. If it doesn't, then your function never returns.

With the modified while loop, that may still happen, but it will result in an infinite loop, and the compiler is fine if you shoot yourself in the foot that way.

Upvotes: 5

David Pilkington
David Pilkington

Reputation: 13630

You can change your else clause to break out of the loop. And then return out of the loop.

        while (true)
        {
            if (weekendDays.Contains(date.DayOfWeek) || 
                      holidayDates.Contains(date))
                date = date.AddDays(1);
            else
                break;
        }
        return date;

Upvotes: 1

Related Questions