Skip to content

Commit 984128f

Browse files
authored
Reduce allocation in TextWriter.NewLine (#121508)
It's reasonably common for a codebase to pick a specific newline string and set it regardless of OS, but currently that ends up allocating on every OS each call to set_NewLine. Two changes: 1. When setting TextWriter.NewLine to the existing value, make it a nop to avoid unnecessarily calling ToCharArray. 2. When setting TextWriter.NewLine to "\n" on Windows or to "\r\n" on Unix, use a cached array.
1 parent 8f1dc6d commit 984128f

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Buffers;
5+
using System.Diagnostics;
56
using System.Diagnostics.CodeAnalysis;
67
using System.Globalization;
78
using System.Runtime.CompilerServices;
@@ -25,6 +26,9 @@ public abstract partial class TextWriter : MarshalByRefObject, IDisposable, IAsy
2526
// We don't want to allocate on every TextWriter creation, so cache the char array.
2627
private static readonly char[] s_coreNewLine = Environment.NewLineConst.ToCharArray();
2728

29+
// s_coreNewLine will be ['\r', '\n'] on Windows and ['\n'] on Unix. This is the opposite, lazily created/cached.
30+
private static char[]? s_otherCoreNewLine;
31+
2832
/// <summary>
2933
/// This is the 'NewLine' property expressed as a char[].
3034
/// It is exposed to subclasses as a protected field for read-only
@@ -112,8 +116,17 @@ public virtual string NewLine
112116
{
113117
value ??= Environment.NewLineConst;
114118

115-
CoreNewLineStr = value;
116-
CoreNewLine = value.ToCharArray();
119+
if (CoreNewLineStr != value)
120+
{
121+
CoreNewLineStr = value;
122+
CoreNewLine =
123+
value == Environment.NewLineConst ? s_coreNewLine : // current OS default
124+
Environment.NewLineConst == "\r\n" && value == "\n" ? (s_otherCoreNewLine ??= ['\n']) : // other OS default
125+
Environment.NewLineConst == "\n" && value == "\r\n" ? (s_otherCoreNewLine ??= ['\r', '\n']) : // other OS default
126+
value.ToCharArray(); // unknown
127+
}
128+
129+
Debug.Assert(CoreNewLineStr == new string(CoreNewLine));
117130
}
118131
}
119132

0 commit comments

Comments
 (0)