2

这是我的简单代码,我使用委托和 lambda 表达式从给定的开始日期和结束日期获取工作日。

我的朋友说他可以在一行中编写整个程序。我该怎么做?

public delegate void GetWorkingDays(DateTime x,DateTime y);
class Program
{
    static void Main(string[] args)
    {
        var dt1 = new DateTime(2012, 10, 3);
        var dt2 = new DateTime(2013, 10, 3);
        System.Collections.ArrayList l = new ArrayList();
        GetWorkingDays d = (d1, d2) =>
        {
            while (d1.Date < d2.Date) 
            {
                if(d1.DayOfWeek == DayOfWeek.Saturday)
                {
                    d1 = d1.AddDays(2);
                    Console.WriteLine();
                }
                else
                {
                   Console.Write(d1.Day + "  ");
                    d1 = d1.AddDays(1);
                }
            } 
        };
        d(dt1, dt2);
    }
};
4

4 回答 4

3

我看不出你怎么能在一行中做到这一点,因为至少需要一行来定义委托,而一行来调用委托。但这是获取工作日的日期并计算它们的一条线。

GetWorkingDays d = (dateFrom, dateTo) =>
        Enumerable
            .Range(0, (int)dateTo.Subtract(dateFrom).TotalDays + 1)
            .Select(x => dateFrom.AddDays(x))
            .Count(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
Console.Writeline("Number of Weekdays is {0}",d(dateFrom, dateTo));

或者

 var days = Enumerable
            .Range(0, (int)d2.Subtract(d1).TotalDays + 1)
            .Select(x => d1.AddDays(x))
            .Count(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
于 2013-11-02T07:39:49.057 回答
1

While this may not answer your question, it's really important to tell you that you shouldn't be doing this at all, for two reasons.

  1. Writing readable code is very very important, and your existing code is as good as it can get. A complex one-liner will not only make it less readable but also make debugging harder. Overall maintenance is a nightmare.

  2. You aim to bring a side effect rather than return a value after some computation. In other words your delegate returns void. A Linq style query is not the way to go here.

And two suggestions:

  1. I saw ArrayList in your code. It is criminal to use it since .NET 2. See this. You will be hailed as a hero if you change it to a List<T>. If your friend is smart he should help you with such basic things rather than being pedantic.

  2. A name that starts with Get... is not a good name for a method (or a delegate) that returns (gets) nothing (void). I would call it WorkingDaysPrinter or so.


Just for the sake of it, your answer would be something like:

WorkingDaysPrinter p = (d1, d2) => Enumerable.Range(0, d2.Subtract(d1).Days)
                                             .Select(x => d1.AddDays(x))
                                             .Where((x, i) => i == 0 || x.DayOfWeek != DayOfWeek.Sunday)
                                             .ToList()
                                             .ForEach(x =>
                                              {
                                                  if (x.DayOfWeek == DayOfWeek.Saturday)
                                                      Console.WriteLine();
                                                  else
                                                      Console.Write(x.Day + " ");
                                              });

It's slightly better to write the query separately and then run a separate foreach:

WorkingDaysPrinter p = (d1, d2) => 
{
    var query = Enumerable.Range(0, d2.Subtract(d1).Days)
                          .Select(x => d1.AddDays(x))
                          .Where((x, i) => i == 0 || x.DayOfWeek != DayOfWeek.Sunday);
    foreach (var day in query)
    {
        if (x.DayOfWeek == DayOfWeek.Saturday)
            Console.WriteLine();
        else
            Console.Write(x.Day + " ");
    });
}

By the looks of it I think it would be better if your delegate returns a list of working days. Something like:

public delegate IEnumerable<DateTime> WorkingDaysGetter(DateTime x, DateTime y);

WorkingDaysGetter g = (d1, d2) => Enumerable.Range(0, d2.Subtract(d1).Days)
                                            .Select(x => d1.AddDays(x))
                                            .Where(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
foreach (var day in g(dt1, dt2))
{
    Console.Write(x.Day + " ");
}
于 2013-11-02T08:36:30.070 回答
0
var count = Enumerable
        .Range(1, (int)y.Subtract(x).TotalDays)
        .Select(x => to.AddDays(x))
        .Count(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
于 2013-11-02T07:48:21.743 回答
0
GetWorkingDays getWorkDays = (d1, d2) =>
    Enumerable.Range(1, (int)(dt2 - dt1).TotalDays)
        .Select(d => dt1.AddDays(d))
        .Where(d => d.DayOfWeek != DayOfWeek.Saturday && d.DayOfWeek != DayOfWeek.Sunday)
        .ToList()
        .ForEach(d => Console.Write(d.Day + " "));
于 2013-11-02T07:51:40.433 回答