C# DateTime.AddDays或新的DateTime

C# DateTime.AddDays或新的DateTime,c#,.net,performance,datetime,stopwatch,C#,.net,Performance,Datetime,Stopwatch,我正在创建一个月的约会清单。我想知道什么会更有效率 List<DateTime> GetDates(DateTime StartDay) { List<DateTime> dates = new List<DateTime>(); int TotalDays=StartDay.AddMonths(1).AddDays(-1).Day; for (int i=1; i<TotalDays; i++) { dates.Add(new Da

我正在创建一个月的约会清单。我想知道什么会更有效率

List<DateTime> GetDates(DateTime StartDay) {
  List<DateTime> dates = new List<DateTime>();
  int TotalDays=StartDay.AddMonths(1).AddDays(-1).Day;
  for (int i=1; i<TotalDays; i++) {
    dates.Add(new DateTime(StartDay.Year, StartDay.Month, i));
  }
  return dates;
}

基本上,new DateTime或DateTime.addDays更有效吗

更新:

static void Main(string[] args) {
  System.Diagnostics.Stopwatch sw=new System.Diagnostics.Stopwatch();
  long t1, t2, total;
  List<DateTime> l;
  DateTime begin = DateTime.Now;
  total = 0L;
  for (int i=0; i<10; i++) {
    sw.Start();
    l = GetDates(begin);
    sw.Stop();


    sw.Stop();
    t1 = sw.ElapsedTicks;
    sw.Reset();
    sw.Start();

    l = GetDates2(begin);
    sw.Stop();
    t2=sw.ElapsedTicks;
    total +=  t1- t2;

    Console.WriteLine("Test {0} : {1} {2} : {3}", i,t1,t2, t1- t2);
  }
  Console.WriteLine("Total: {0}", total);

  Console.WriteLine("\n\nDone");
  Console.ReadLine();
}

static List<DateTime> GetDates(DateTime StartDay) {
  List<DateTime> dates = new List<DateTime>();
  int TotalDays=StartDay.AddMonths(10000).AddDays(-1).Day;
  for (int i=1; i<TotalDays; i++) {
    dates.Add(new DateTime(StartDay.Year, StartDay.Month, i));
  }
  return dates;
}


static List<DateTime> GetDates2(DateTime StartDay) {
  List<DateTime> dates = new List<DateTime>();
  DateTime NextMonth = StartDay.AddMonths(10000);
  for (DateTime curr=StartDay; !curr.Equals(NextMonth); curr=curr.AddDays(1)) {
    dates.Add(curr);
  }
  return dates;
}

结果总是负面的。。。相反,看起来构造函数和整数测试是更有效的方法。

测量它-编写一个测试程序,看看哪一个需要更少的时间。

我相信datetime操作返回新的datetime结构,因此您将以任何方式创建新实例


因为他们最终都做了相同的事情,所以没有太大区别


如果你想提高效率,就用记号吧。我在DateTime中看到的所有调用最终都会在完成任何计算之前转换为滴答声。

除非您正在进行一些财务处理,否则我更担心的是可读性而不是性能。只有在这里这样的地方开始担心性能,如果它已经被证明是一个瓶颈。

我同意Mark的观点。自己测试这两种方法,看看哪一种更快。使用Stopwatch类可以获得每个方法运行所需时间的精确计时。我的第一个猜测是,既然两者最终都创造了新的结构,那么任何速度差都可以忽略不计。另外,由于最多只能生成一个月的31天的日期,我认为这两种方法都不会比另一种慢很多。可能是你生成了数千或数百万个日期,这会产生影响,但对于31个日期,这可能是过早的优化。

很难想象这会产生显著影响,但Reflector表明AddDays技术应该更有效

比较AddDays与AddDouble、Int32的核心逻辑

AddDays只是将指定的天数转换为相当于长时间的刻度数,并将其添加到现有的刻度中

使用年/月/日构造函数创建新的DateTime需要更多的计算。构造器必须检查指定的年份是否是闰年,在每个月分配一个天数数组,执行一系列额外的操作,最终得到这三个数字所代表的刻度数


编辑:DateTime.AddDaysint比新的DateTimeint,int,int快,但是第一个算法比第二个算法快。这可能是因为第二种算法的迭代成本要高得多。正如您在编辑中所观察到的,这很可能是因为DateTime.Equals比比较整数更昂贵。

这是一个正在运行的测试程序,实现了一些算法,以便能够对它们进行实际比较,但它们仍然需要工作:

 class Program
    {
        static void Main(string[] args)
        {
            IList<DateTime> l1, l2;
            DateTime begin = new DateTime(2000, 1, 1);

            Stopwatch timer1 = Stopwatch.StartNew();
            for (int i = 0; i < 10000; i++)
                l1 = GetDates(begin);
            timer1.Stop();

            Stopwatch timer2 = Stopwatch.StartNew();
            for (int i = 0; i < 10000; i++)
                l2 = GetDates2(begin);
            timer2.Stop();

            Console.WriteLine("new DateTime: {0}\n.AddDays: {1}",
                timer1.ElapsedTicks, timer2.ElapsedTicks);
            Console.ReadLine();
        }

        static IList<DateTime> GetDates(DateTime StartDay)
        {
            IList<DateTime> dates = new List<DateTime>();

            int TotalDays = DateTime.DaysInMonth(StartDay.Year, StartDay.Month);

            for (int i = 0; i < TotalDays; i++)
                dates.Add(new DateTime(StartDay.Year, StartDay.Month, i + 1));

            return dates;
        }


        static IList<DateTime> GetDates2(DateTime StartDay)
        {
            IList<DateTime> dates = new List<DateTime>();

            DateTime NextMonth = StartDay.AddMonths(1);

            for (DateTime curr = StartDay; !curr.Equals(NextMonth); curr = curr.AddDays(1))
                dates.Add(curr);

            return dates;
        }
    } // class
输出I添加了逗号:

new DateTime: 545,307,375 .AddDays: 180,071,512
这些结果对我来说似乎很清楚,但老实说,我认为它们会更接近。

请注意:第一个代码示例不起作用-DateTime.Day返回月份的日期。如果你想要这个数量,可以使用时间跨度。好的,那么,对于2009年1月1日,它会加上一个月2009年2月1日,减去一天2009年1月31日,然后给我我我想要的第31天部分。从上下文来看,StartDay不能假设从月的第一天开始。如果我从本月5号开始,我会在4号结束使用该代码。如果您总是在月边界上,我建议使用DateTime.DaysInMonth静态函数。啊,现在就知道了-如果您修改第二个测试,使其与第一个测试完全相同,但替换日期。Addnew DateTimeStartDay.Year,StartDay.month,I with dates.AddStartDay.AddDays1,第二个版本的执行速度大约是第一个版本的两倍。第一次测试运行将比任何后续运行都慢,无论您使用哪种算法。您应该真正使用System.Diagnostics.Stopwatch进行计时。在此处报告您的结果:您相信吗?引用它不是更好吗?此方法不会更改此DateTime的值。相反,将返回一个新的DateTime,其值是此操作的结果。此外,尽管它们都创建了新的DateTime实例,但这两个构造函数涉及非常不同的算法。你批评我的措辞吗?我觉得我写它的方式和包含链接的方式更为礼貌。虽然它们都创建了新实例,但它们肯定不会做相同的事情。它们最终做了相同的事情,这两种方法之间的区别不大。别胡说八道,伙计。不仅如此,在分析第一行的时候,你完全忽略了第二行,这说明了一个事实,处理日期时间结构最有效的方法就是只使用滴答声。哎呀,我同意。我同意第二部分,我的愤怒已经激起。必须粉碎。+1,这绝对是最重要的建议。我对这件事深究了一下,觉得有点傻。D:
long num = (long) ((value * scale) + ((value >= 0.0) ? 0.5 : -0.5));
if ((num <= -315537897600000L) || (num >= 0x11efae44cb400L)) {
    // Throw omitted
}
return this.AddTicks(num * 0x2710L);
if (((year >= 1) && (year <= 0x270f)) && ((month >= 1) && (month <= 12)))
{
    int[] numArray = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365;
    if ((day >= 1) && (day <= (numArray[month] - numArray[month - 1])))
    {
        int num = year - 1;
        int num2 = ((((((num * 0x16d) + (num / 4)) - (num / 100)) + (num / 400)) + numArray[month - 1]) + day) - 1;
        return (num2 * 0xc92a69c000L);
    }
}
// Throw omitted
 class Program
    {
        static void Main(string[] args)
        {
            IList<DateTime> l1, l2;
            DateTime begin = new DateTime(2000, 1, 1);

            Stopwatch timer1 = Stopwatch.StartNew();
            for (int i = 0; i < 10000; i++)
                l1 = GetDates(begin);
            timer1.Stop();

            Stopwatch timer2 = Stopwatch.StartNew();
            for (int i = 0; i < 10000; i++)
                l2 = GetDates2(begin);
            timer2.Stop();

            Console.WriteLine("new DateTime: {0}\n.AddDays: {1}",
                timer1.ElapsedTicks, timer2.ElapsedTicks);
            Console.ReadLine();
        }

        static IList<DateTime> GetDates(DateTime StartDay)
        {
            IList<DateTime> dates = new List<DateTime>();

            int TotalDays = DateTime.DaysInMonth(StartDay.Year, StartDay.Month);

            for (int i = 0; i < TotalDays; i++)
                dates.Add(new DateTime(StartDay.Year, StartDay.Month, i + 1));

            return dates;
        }


        static IList<DateTime> GetDates2(DateTime StartDay)
        {
            IList<DateTime> dates = new List<DateTime>();

            DateTime NextMonth = StartDay.AddMonths(1);

            for (DateTime curr = StartDay; !curr.Equals(NextMonth); curr = curr.AddDays(1))
                dates.Add(curr);

            return dates;
        }
    } // class
new DateTime: 545,307,375 .AddDays: 180,071,512