Avoid unnecessary array allocation in DateTimeParse (#84964)
authorStephen Toub <stoub@microsoft.com>
Tue, 18 Apr 2023 23:22:21 +0000 (19:22 -0400)
committerGitHub <noreply@github.com>
Tue, 18 Apr 2023 23:22:21 +0000 (19:22 -0400)
When using DateTime{Offset}.ParseExact with a culture that employs genitive month names, the public DateTimeFormatInfo.AbbreviatedMonthGenitiveNames and DateTimeFormatInfo.MonthGenitiveNames properties are being accessed to get a string[] of the month names, but those properties clone.  If we instead access the internal non-cloning version, we save on an array allocation on each parse.

src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs
src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs

index 6d07fa3..e661479 100644 (file)
@@ -1204,7 +1204,7 @@ namespace System.Globalization
         /// Retrieve the array which contains the month names in genitive form.
         /// If this culture does not use the genitive form, the normal month name is returned.
         /// </summary>
-        private string[] InternalGetGenitiveMonthNames(bool abbreviated)
+        internal string[] InternalGetGenitiveMonthNames(bool abbreviated)
         {
             if (abbreviated)
             {
index ca1594b..ddf5bae 100644 (file)
@@ -3353,7 +3353,7 @@ new DS[] { DS.ERROR,  DS.TX_NNN,  DS.TX_NNN,  DS.TX_NNN,  DS.ERROR,   DS.ERROR,
                 // Search genitive form.
                 if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
                 {
-                    int tempResult = str.MatchLongestWords(dtfi.AbbreviatedMonthGenitiveNames, ref maxMatchStrLen);
+                    int tempResult = str.MatchLongestWords(dtfi.InternalGetGenitiveMonthNames(abbreviated: true), ref maxMatchStrLen);
 
                     // We found a longer match in the genitive month name.  Use this as the result.
                     // tempResult + 1 should be the month value.
@@ -3453,7 +3453,7 @@ new DS[] { DS.ERROR,  DS.TX_NNN,  DS.TX_NNN,  DS.TX_NNN,  DS.ERROR,   DS.ERROR,
                 // Search genitive form.
                 if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
                 {
-                    int tempResult = str.MatchLongestWords(dtfi.MonthGenitiveNames, ref maxMatchStrLen);
+                    int tempResult = str.MatchLongestWords(dtfi.InternalGetGenitiveMonthNames(abbreviated: false), ref maxMatchStrLen);
                     // We found a longer match in the genitive month name.  Use this as the result.
                     // The result from MatchLongestWords is 0 ~ length of word array.
                     // So we increment the result by one to become the month value.