Explorar el Código

Reduce allocation in Index/Range.ToString (dotnet/coreclr#21755)

* Reduce allocation in Index/Range.ToString

* Address PR feedback

Signed-off-by: dotnet-bot <[email protected]>
Stephen Toub hace 7 años
padre
commit
d3747f620b

+ 10 - 3
netcore/System.Private.CoreLib/shared/System/Index.cs

@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics;
+
 namespace System
 {
     public readonly struct Index : IEquatable<Index>
@@ -28,10 +30,15 @@ namespace System
             return _value;
         }
 
-        public override string ToString()
+        public override string ToString() => FromEnd ? ToStringFromEnd() : ((uint)Value).ToString();
+
+        private string ToStringFromEnd()
         {
-            string str = Value.ToString();
-            return FromEnd ? "^" + str : str;
+            Span<char> span = stackalloc char[11]; // 1 for ^ and 10 for longest possible uint value
+            bool formatted = ((uint)Value).TryFormat(span.Slice(1), out int charsWritten);
+            Debug.Assert(formatted);
+            span[0] = '^';
+            return new string(span.Slice(0, charsWritten + 1));
         }
 
         public static implicit operator Index(int value)

+ 27 - 1
netcore/System.Private.CoreLib/shared/System/Range.cs

@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics;
+
 namespace System
 {
     public readonly struct Range : IEquatable<Range>
@@ -35,7 +37,31 @@ namespace System
 
         public override string ToString()
         {
-            return Start + ".." + End;
+            Span<char> span = stackalloc char[2 + (2 * 11)]; // 2 for "..", then for each index 1 for '^' and 10 for longest possible uint
+            int charsWritten;
+            int pos = 0;
+
+            if (Start.FromEnd)
+            {
+                span[0] = '^';
+                pos = 1;
+            }
+            bool formatted = ((uint)Start.Value).TryFormat(span.Slice(pos), out charsWritten);
+            Debug.Assert(formatted);
+            pos += charsWritten;
+
+            span[pos++] = '.';
+            span[pos++] = '.';
+
+            if (End.FromEnd)
+            {
+                span[pos++] = '^';
+            }
+            formatted = ((uint)End.Value).TryFormat(span.Slice(pos), out charsWritten);
+            Debug.Assert(formatted);
+            pos += charsWritten;
+
+            return new string(span.Slice(0, pos));
         }
 
         public static Range Create(Index start, Index end) => new Range(start, end);