Bu @Sergey ve @ Steffen'ın cevapları hakkında daha uzun bir yorum. Geçmişte kendime benzer bir kod yazdıktan sonra , netliğin de önemli olduğunu hatırlarken en çok neyin performans gösterdiğini kontrol etmeye karar verdim .
Sonuç
İşte 10 milyon yineleme için örnek bir test çalıştırması sonucu:
2257 ms for FirstDayOfMonth_AddMethod()
2406 ms for FirstDayOfMonth_NewMethod()
6342 ms for LastDayOfMonth_AddMethod()
4037 ms for LastDayOfMonth_AddMethodWithDaysInMonth()
4160 ms for LastDayOfMonth_NewMethod()
4212 ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()
2491 ms for LastDayOfMonth_SpecialCase()
kod
Ben kullanılan LINQPad 4 açık derleyici optimizasyon testler (C # Program mod). Açıklık ve rahatlık için Uzantı yöntemleri olarak kabul edilen test edilmiş kod:
public static class DateTimeDayOfMonthExtensions
{
public static DateTime FirstDayOfMonth_AddMethod(this DateTime value)
{
return value.Date.AddDays(1 - value.Day);
}
public static DateTime FirstDayOfMonth_NewMethod(this DateTime value)
{
return new DateTime(value.Year, value.Month, 1);
}
public static DateTime LastDayOfMonth_AddMethod(this DateTime value)
{
return value.FirstDayOfMonth_AddMethod().AddMonths(1).AddDays(-1);
}
public static DateTime LastDayOfMonth_AddMethodWithDaysInMonth(this DateTime value)
{
return value.Date.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - value.Day);
}
public static DateTime LastDayOfMonth_SpecialCase(this DateTime value)
{
return value.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - 1);
}
public static int DaysInMonth(this DateTime value)
{
return DateTime.DaysInMonth(value.Year, value.Month);
}
public static DateTime LastDayOfMonth_NewMethod(this DateTime value)
{
return new DateTime(value.Year, value.Month, DateTime.DaysInMonth(value.Year, value.Month));
}
public static DateTime LastDayOfMonth_NewMethodWithReuseOfExtMethod(this DateTime value)
{
return new DateTime(value.Year, value.Month, value.DaysInMonth());
}
}
void Main()
{
Random rnd = new Random();
DateTime[] sampleData = new DateTime[10000000];
for(int i = 0; i < sampleData.Length; i++) {
sampleData[i] = new DateTime(1970, 1, 1).AddDays(rnd.Next(0, 365 * 50));
}
GC.Collect();
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].FirstDayOfMonth_AddMethod();
}
string.Format("{0} ms for FirstDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump();
GC.Collect();
sw.Restart();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].FirstDayOfMonth_NewMethod();
}
string.Format("{0} ms for FirstDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump();
GC.Collect();
sw.Restart();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].LastDayOfMonth_AddMethod();
}
string.Format("{0} ms for LastDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump();
GC.Collect();
sw.Restart();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].LastDayOfMonth_AddMethodWithDaysInMonth();
}
string.Format("{0} ms for LastDayOfMonth_AddMethodWithDaysInMonth()", sw.ElapsedMilliseconds).Dump();
GC.Collect();
sw.Restart();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].LastDayOfMonth_NewMethod();
}
string.Format("{0} ms for LastDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump();
GC.Collect();
sw.Restart();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].LastDayOfMonth_NewMethodWithReuseOfExtMethod();
}
string.Format("{0} ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()", sw.ElapsedMilliseconds).Dump();
for(int i = 0; i < sampleData.Length; i++) {
sampleData[i] = sampleData[i].FirstDayOfMonth_AddMethod();
}
GC.Collect();
sw.Restart();
for(int i = 0; i < sampleData.Length; i++) {
DateTime test = sampleData[i].LastDayOfMonth_SpecialCase();
}
string.Format("{0} ms for LastDayOfMonth_SpecialCase()", sw.ElapsedMilliseconds).Dump();
}
analiz
Bu sonuçlardan bazıları beni şaşırttı.
Çok fazla olmamasına rağmen , testin çoğu çalışmasından FirstDayOfMonth_AddMethod
biraz daha hızlıydı FirstDayOfMonth_NewMethod
. Ancak, ikincisinin biraz daha net bir niyeti olduğunu düşünüyorum ve bu yüzden bunun için bir tercihim var.
LastDayOfMonth_AddMethod
karşı net bir kaybeden oldu LastDayOfMonth_AddMethodWithDaysInMonth
, LastDayOfMonth_NewMethod
ve LastDayOfMonth_NewMethodWithReuseOfExtMethod
. En hızlı üç arasında çok fazla bir şey yok ve bu yüzden kişisel tercihinize bağlı. LastDayOfMonth_NewMethodWithReuseOfExtMethod
Başka bir yararlı uzantı yöntemini yeniden kullanmasıyla netliği seçiyorum . IMHO'nun amacı daha açık ve küçük performans maliyetini kabul etmeye hazırım.
LastDayOfMonth_SpecialCase
o tarihi zaten hesaplamış olabileceğiniz özel durumda ayın ilkini sağladığınızı DateTime.DaysInMonth
ve sonucu almak için add yöntemini kullandığını varsayar . Bu, diğer versiyonlardan daha hızlı, beklediğiniz gibi, ancak hıza karşı çaresiz bir ihtiyaç duymadıkça, bu özel durumu cephaneliğinizde görmüyorum.
Sonuç
İşte benim seçimler ile bir uzatma yöntemi sınıfı ve genel olarak @Steffen ile anlaşma inanıyorum:
public static class DateTimeDayOfMonthExtensions
{
public static DateTime FirstDayOfMonth(this DateTime value)
{
return new DateTime(value.Year, value.Month, 1);
}
public static int DaysInMonth(this DateTime value)
{
return DateTime.DaysInMonth(value.Year, value.Month);
}
public static DateTime LastDayOfMonth(this DateTime value)
{
return new DateTime(value.Year, value.Month, value.DaysInMonth());
}
}
Eğer bu kadar ilerlemişseniz, zaman ayırdığınız için teşekkürler! Eğlenceliydi: ¬). Bu algoritmalar için başka önerileriniz varsa lütfen yorum yapın.
_Date
Değişkende saklanan tek bir değer vardır . Bu değerden ne "min ve maks" almaya çalışıyorsunuz?