1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 using System
.Threading
;
7 using System
.Globalization
;
8 using System
.Threading
.Tasks
;
9 using System
.Runtime
.CompilerServices
;
10 using System
.Runtime
.InteropServices
;
12 using System
.Diagnostics
.CodeAnalysis
;
16 // This abstract base class represents a writer that can write a sequential
17 // stream of characters. A subclass must minimally implement the
18 // Write(char) method.
20 // This class is intended for character output, not bytes.
21 // There are methods on the Stream class for writing bytes.
22 public abstract partial class TextWriter
: MarshalByRefObject
, IDisposable
, IAsyncDisposable
24 public static readonly TextWriter Null
= new NullTextWriter();
26 // We don't want to allocate on every TextWriter creation, so cache the char array.
27 private static readonly char[] s_coreNewLine
= Environment
.NewLine
.ToCharArray();
30 /// This is the 'NewLine' property expressed as a char[].
31 /// It is exposed to subclasses as a protected field for read-only
32 /// purposes. You should only modify it by using the 'NewLine' property.
33 /// In particular you should never modify the elements of the array
34 /// as they are shared among many instances of TextWriter.
36 protected char[] CoreNewLine
= s_coreNewLine
;
37 private string CoreNewLineStr
= Environment
.NewLine
;
39 // Can be null - if so, ask for the Thread's CurrentCulture every time.
40 private readonly IFormatProvider
? _internalFormatProvider
;
42 protected TextWriter()
44 _internalFormatProvider
= null; // Ask for CurrentCulture all the time.
47 protected TextWriter(IFormatProvider
? formatProvider
)
49 _internalFormatProvider
= formatProvider
;
52 public virtual IFormatProvider FormatProvider
56 if (_internalFormatProvider
== null)
58 return CultureInfo
.CurrentCulture
;
62 return _internalFormatProvider
;
67 public virtual void Close()
70 GC
.SuppressFinalize(this);
73 protected virtual void Dispose(bool disposing
)
80 GC
.SuppressFinalize(this);
83 public virtual ValueTask
DisposeAsync()
92 return new ValueTask(Task
.FromException(exc
));
96 // Clears all buffers for this TextWriter and causes any buffered data to be
97 // written to the underlying device. This default method is empty, but
98 // descendant classes can override the method to provide the appropriate
100 public virtual void Flush()
104 public abstract Encoding Encoding
110 /// Returns the line terminator string used by this TextWriter. The default line
111 /// terminator string is Environment.NewLine, which is platform specific.
112 /// On Windows this is a carriage return followed by a line feed ("\r\n").
113 /// On OSX and Linux this is a line feed ("\n").
116 /// The line terminator string is written to the text stream whenever one of the
117 /// WriteLine methods are called. In order for text written by
118 /// the TextWriter to be readable by a TextReader, only one of the following line
119 /// terminator strings should be used: "\r", "\n", or "\r\n".
122 public virtual string NewLine
124 get { return CoreNewLineStr; }
129 value = Environment
.NewLine
;
132 CoreNewLineStr
= value;
133 CoreNewLine
= value.ToCharArray();
138 // Writes a character to the text stream. This default method is empty,
139 // but descendant classes can override the method to provide the
140 // appropriate functionality.
142 public virtual void Write(char value)
146 // Writes a character array to the text stream. This default method calls
147 // Write(char) for each of the characters in the character array.
148 // If the character array is null, nothing is written.
150 public virtual void Write(char[]? buffer
)
154 Write(buffer
, 0, buffer
.Length
);
158 // Writes a range of a character array to the text stream. This method will
159 // write count characters of data into this TextWriter from the
160 // buffer character array starting at position index.
162 public virtual void Write(char[] buffer
, int index
, int count
)
166 throw new ArgumentNullException(nameof(buffer
), SR
.ArgumentNull_Buffer
);
170 throw new ArgumentOutOfRangeException(nameof(index
), SR
.ArgumentOutOfRange_NeedNonNegNum
);
174 throw new ArgumentOutOfRangeException(nameof(count
), SR
.ArgumentOutOfRange_NeedNonNegNum
);
176 if (buffer
.Length
- index
< count
)
178 throw new ArgumentException(SR
.Argument_InvalidOffLen
);
181 for (int i
= 0; i
< count
; i
++) Write(buffer
[index
+ i
]);
184 // Writes a span of characters to the text stream.
186 public virtual void Write(ReadOnlySpan
<char> buffer
)
188 char[] array
= ArrayPool
<char>.Shared
.Rent(buffer
.Length
);
192 buffer
.CopyTo(new Span
<char>(array
));
193 Write(array
, 0, buffer
.Length
);
197 ArrayPool
<char>.Shared
.Return(array
);
201 // Writes the text representation of a boolean to the text stream. This
202 // method outputs either bool.TrueString or bool.FalseString.
204 public virtual void Write(bool value)
206 Write(value ? "True" : "False");
209 // Writes the text representation of an integer to the text stream. The
210 // text representation of the given value is produced by calling the
211 // int.ToString() method.
213 public virtual void Write(int value)
215 Write(value.ToString(FormatProvider
));
218 // Writes the text representation of an integer to the text stream. The
219 // text representation of the given value is produced by calling the
220 // uint.ToString() method.
222 [CLSCompliant(false)]
223 public virtual void Write(uint value)
225 Write(value.ToString(FormatProvider
));
228 // Writes the text representation of a long to the text stream. The
229 // text representation of the given value is produced by calling the
230 // long.ToString() method.
232 public virtual void Write(long value)
234 Write(value.ToString(FormatProvider
));
237 // Writes the text representation of an unsigned long to the text
238 // stream. The text representation of the given value is produced
239 // by calling the ulong.ToString() method.
241 [CLSCompliant(false)]
242 public virtual void Write(ulong value)
244 Write(value.ToString(FormatProvider
));
247 // Writes the text representation of a float to the text stream. The
248 // text representation of the given value is produced by calling the
249 // float.ToString(float) method.
251 public virtual void Write(float value)
253 Write(value.ToString(FormatProvider
));
256 // Writes the text representation of a double to the text stream. The
257 // text representation of the given value is produced by calling the
258 // double.ToString(double) method.
260 public virtual void Write(double value)
262 Write(value.ToString(FormatProvider
));
265 public virtual void Write(decimal value)
267 Write(value.ToString(FormatProvider
));
270 // Writes a string to the text stream. If the given string is null, nothing
271 // is written to the text stream.
273 public virtual void Write(string? value)
277 Write(value.ToCharArray());
281 // Writes the text representation of an object to the text stream. If the
282 // given object is null, nothing is written to the text stream.
283 // Otherwise, the object's ToString method is called to produce the
284 // string representation, and the resulting string is then written to the
287 public virtual void Write(object? value)
291 if (value is IFormattable f
)
293 Write(f
.ToString(null, FormatProvider
));
296 Write(value.ToString());
301 /// Equivalent to Write(stringBuilder.ToString()) however it uses the
302 /// StringBuilder.GetChunks() method to avoid creating the intermediate string
304 /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
305 public virtual void Write(StringBuilder
? value)
309 foreach (ReadOnlyMemory
<char> chunk
in value.GetChunks())
314 // Writes out a formatted string. Uses the same semantics as
317 public virtual void Write(string format
, object? arg0
)
319 Write(string.Format(FormatProvider
, format
, arg0
));
322 // Writes out a formatted string. Uses the same semantics as
325 public virtual void Write(string format
, object? arg0
, object? arg1
)
327 Write(string.Format(FormatProvider
, format
, arg0
, arg1
));
330 // Writes out a formatted string. Uses the same semantics as
333 public virtual void Write(string format
, object? arg0
, object? arg1
, object? arg2
)
335 Write(string.Format(FormatProvider
, format
, arg0
, arg1
, arg2
));
338 // Writes out a formatted string. Uses the same semantics as
341 public virtual void Write(string format
, params object?[] arg
)
343 Write(string.Format(FormatProvider
, format
, arg
));
347 // Writes a line terminator to the text stream. The default line terminator
348 // is Environment.NewLine, but this value can be changed by setting the NewLine property.
350 public virtual void WriteLine()
355 // Writes a character followed by a line terminator to the text stream.
357 public virtual void WriteLine(char value)
363 // Writes an array of characters followed by a line terminator to the text
366 public virtual void WriteLine(char[]? buffer
)
372 // Writes a range of a character array followed by a line terminator to the
375 public virtual void WriteLine(char[] buffer
, int index
, int count
)
377 Write(buffer
, index
, count
);
381 public virtual void WriteLine(ReadOnlySpan
<char> buffer
)
383 char[] array
= ArrayPool
<char>.Shared
.Rent(buffer
.Length
);
387 buffer
.CopyTo(new Span
<char>(array
));
388 WriteLine(array
, 0, buffer
.Length
);
392 ArrayPool
<char>.Shared
.Return(array
);
396 // Writes the text representation of a boolean followed by a line
397 // terminator to the text stream.
399 public virtual void WriteLine(bool value)
405 // Writes the text representation of an integer followed by a line
406 // terminator to the text stream.
408 public virtual void WriteLine(int value)
414 // Writes the text representation of an unsigned integer followed by
415 // a line terminator to the text stream.
417 [CLSCompliant(false)]
418 public virtual void WriteLine(uint value)
424 // Writes the text representation of a long followed by a line terminator
425 // to the text stream.
427 public virtual void WriteLine(long value)
433 // Writes the text representation of an unsigned long followed by
434 // a line terminator to the text stream.
436 [CLSCompliant(false)]
437 public virtual void WriteLine(ulong value)
443 // Writes the text representation of a float followed by a line terminator
444 // to the text stream.
446 public virtual void WriteLine(float value)
452 // Writes the text representation of a double followed by a line terminator
453 // to the text stream.
455 public virtual void WriteLine(double value)
461 public virtual void WriteLine(decimal value)
467 // Writes a string followed by a line terminator to the text stream.
469 public virtual void WriteLine(string? value)
475 Write(CoreNewLineStr
);
479 /// Equivalent to WriteLine(stringBuilder.ToString()) however it uses the
480 /// StringBuilder.GetChunks() method to avoid creating the intermediate string
482 public virtual void WriteLine(StringBuilder
? value)
488 // Writes the text representation of an object followed by a line
489 // terminator to the text stream.
491 public virtual void WriteLine(object? value)
499 // Call WriteLine(value.ToString), not Write(Object), WriteLine().
500 // This makes calls to WriteLine(Object) atomic.
501 if (value is IFormattable f
)
503 WriteLine(f
.ToString(null, FormatProvider
));
507 WriteLine(value.ToString());
512 // Writes out a formatted string and a new line. Uses the same
513 // semantics as string.Format.
515 public virtual void WriteLine(string format
, object? arg0
)
517 WriteLine(string.Format(FormatProvider
, format
, arg0
));
520 // Writes out a formatted string and a new line. Uses the same
521 // semantics as string.Format.
523 public virtual void WriteLine(string format
, object? arg0
, object? arg1
)
525 WriteLine(string.Format(FormatProvider
, format
, arg0
, arg1
));
528 // Writes out a formatted string and a new line. Uses the same
529 // semantics as string.Format.
531 public virtual void WriteLine(string format
, object? arg0
, object? arg1
, object? arg2
)
533 WriteLine(string.Format(FormatProvider
, format
, arg0
, arg1
, arg2
));
536 // Writes out a formatted string and a new line. Uses the same
537 // semantics as string.Format.
539 public virtual void WriteLine(string format
, params object?[] arg
)
541 WriteLine(string.Format(FormatProvider
, format
, arg
));
544 #region Task based Async APIs
545 public virtual Task
WriteAsync(char value)
547 var tuple
= new Tuple
<TextWriter
, char>(this, value);
548 return Task
.Factory
.StartNew(state
=>
550 var t
= (Tuple
<TextWriter
, char>)state
!;
551 t
.Item1
.Write(t
.Item2
);
553 tuple
, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
556 public virtual Task
WriteAsync(string? value)
558 var tuple
= new Tuple
<TextWriter
, string?>(this, value);
559 return Task
.Factory
.StartNew(state
=>
561 var t
= (Tuple
<TextWriter
, string?>)state
!;
562 t
.Item1
.Write(t
.Item2
);
564 tuple
, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
568 /// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
569 /// StringBuilder.GetChunks() method to avoid creating the intermediate string
571 /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
572 public virtual Task
WriteAsync(StringBuilder
? value, CancellationToken cancellationToken
= default)
575 cancellationToken
.IsCancellationRequested
? Task
.FromCanceled(cancellationToken
) :
576 value == null ? Task
.CompletedTask
:
577 WriteAsyncCore(value, cancellationToken
);
579 async Task
WriteAsyncCore(StringBuilder sb
, CancellationToken ct
)
581 foreach (ReadOnlyMemory
<char> chunk
in sb
.GetChunks())
583 await WriteAsync(chunk
, ct
).ConfigureAwait(false);
588 public Task
WriteAsync(char[]? buffer
)
592 return Task
.CompletedTask
;
595 return WriteAsync(buffer
, 0, buffer
.Length
);
598 public virtual Task
WriteAsync(char[] buffer
, int index
, int count
)
600 var tuple
= new Tuple
<TextWriter
, char[], int, int>(this, buffer
, index
, count
);
601 return Task
.Factory
.StartNew(state
=>
603 var t
= (Tuple
<TextWriter
, char[], int, int>)state
!;
604 t
.Item1
.Write(t
.Item2
, t
.Item3
, t
.Item4
);
606 tuple
, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
609 public virtual Task
WriteAsync(ReadOnlyMemory
<char> buffer
, CancellationToken cancellationToken
= default) =>
610 cancellationToken
.IsCancellationRequested
? Task
.FromCanceled(cancellationToken
) :
611 MemoryMarshal
.TryGetArray(buffer
, out ArraySegment
<char> array
) ?
612 WriteAsync(array
.Array
!, array
.Offset
, array
.Count
) :
613 Task
.Factory
.StartNew(state
=>
615 var t
= (Tuple
<TextWriter
, ReadOnlyMemory
<char>>)state
!;
616 t
.Item1
.Write(t
.Item2
.Span
);
617 }, Tuple
.Create(this, buffer
), cancellationToken
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
619 public virtual Task
WriteLineAsync(char value)
621 var tuple
= new Tuple
<TextWriter
, char>(this, value);
622 return Task
.Factory
.StartNew(state
=>
624 var t
= (Tuple
<TextWriter
, char>)state
!;
625 t
.Item1
.WriteLine(t
.Item2
);
627 tuple
, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
630 public virtual Task
WriteLineAsync(string? value)
632 var tuple
= new Tuple
<TextWriter
, string?>(this, value);
633 return Task
.Factory
.StartNew(state
=>
635 var t
= (Tuple
<TextWriter
, string?>)state
!;
636 t
.Item1
.WriteLine(t
.Item2
);
638 tuple
, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
642 /// Equivalent to WriteLineAsync(stringBuilder.ToString()) however it uses the
643 /// StringBuilder.GetChunks() method to avoid creating the intermediate string
645 /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
646 public virtual Task
WriteLineAsync(StringBuilder
? value, CancellationToken cancellationToken
= default)
649 cancellationToken
.IsCancellationRequested
? Task
.FromCanceled(cancellationToken
) :
650 value == null ? WriteAsync(CoreNewLine
, cancellationToken
) :
651 WriteLineAsyncCore(value, cancellationToken
);
653 async Task
WriteLineAsyncCore(StringBuilder sb
, CancellationToken ct
)
655 foreach (ReadOnlyMemory
<char> chunk
in sb
.GetChunks())
657 await WriteAsync(chunk
, ct
).ConfigureAwait(false);
659 await WriteAsync(CoreNewLine
, ct
).ConfigureAwait(false);
663 public Task
WriteLineAsync(char[]? buffer
)
667 return WriteLineAsync();
670 return WriteLineAsync(buffer
, 0, buffer
.Length
);
673 public virtual Task
WriteLineAsync(char[] buffer
, int index
, int count
)
675 var tuple
= new Tuple
<TextWriter
, char[], int, int>(this, buffer
, index
, count
);
676 return Task
.Factory
.StartNew(state
=>
678 var t
= (Tuple
<TextWriter
, char[], int, int>)state
!;
679 t
.Item1
.WriteLine(t
.Item2
, t
.Item3
, t
.Item4
);
681 tuple
, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
684 public virtual Task
WriteLineAsync(ReadOnlyMemory
<char> buffer
, CancellationToken cancellationToken
= default) =>
685 cancellationToken
.IsCancellationRequested
? Task
.FromCanceled(cancellationToken
) :
686 MemoryMarshal
.TryGetArray(buffer
, out ArraySegment
<char> array
) ?
687 WriteLineAsync(array
.Array
!, array
.Offset
, array
.Count
) :
688 Task
.Factory
.StartNew(state
=>
690 var t
= (Tuple
<TextWriter
, ReadOnlyMemory
<char>>)state
!;
691 t
.Item1
.WriteLine(t
.Item2
.Span
);
692 }, Tuple
.Create(this, buffer
), cancellationToken
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
694 public virtual Task
WriteLineAsync()
696 return WriteAsync(CoreNewLine
);
699 public virtual Task
FlushAsync()
701 return Task
.Factory
.StartNew(state
=>
703 ((TextWriter
)state
!).Flush();
705 this, CancellationToken
.None
, TaskCreationOptions
.DenyChildAttach
, TaskScheduler
.Default
);
709 private sealed class NullTextWriter
: TextWriter
711 internal NullTextWriter() : base(CultureInfo
.InvariantCulture
)
715 public override Encoding Encoding
=> Encoding
.Unicode
;
717 public override void Write(char[] buffer
, int index
, int count
)
721 public override void Write(string? value)
725 // Not strictly necessary, but for perf reasons
726 public override void WriteLine()
730 // Not strictly necessary, but for perf reasons
731 public override void WriteLine(string? value)
735 public override void WriteLine(object? value)
739 public override void Write(char value)
744 public static TextWriter
Synchronized(TextWriter writer
)
747 throw new ArgumentNullException(nameof(writer
));
749 return writer
is SyncTextWriter
? writer
: new SyncTextWriter(writer
);
752 internal sealed class SyncTextWriter
: TextWriter
, IDisposable
754 private readonly TextWriter _out
;
756 internal SyncTextWriter(TextWriter t
) : base(t
.FormatProvider
)
761 public override Encoding Encoding
=> _out
.Encoding
;
763 public override IFormatProvider FormatProvider
=> _out
.FormatProvider
;
766 public override string NewLine
768 [MethodImpl(MethodImplOptions
.Synchronized
)]
769 get { return _out.NewLine; }
770 [MethodImpl(MethodImplOptions
.Synchronized
)]
771 set { _out.NewLine = value; }
774 [MethodImpl(MethodImplOptions
.Synchronized
)]
775 public override void Close() => _out
.Close();
777 [MethodImpl(MethodImplOptions
.Synchronized
)]
778 protected override void Dispose(bool disposing
)
780 // Explicitly pick up a potentially methodimpl'ed Dispose
782 ((IDisposable
)_out
).Dispose();
785 [MethodImpl(MethodImplOptions
.Synchronized
)]
786 public override void Flush() => _out
.Flush();
788 [MethodImpl(MethodImplOptions
.Synchronized
)]
789 public override void Write(char value) => _out
.Write(value);
791 [MethodImpl(MethodImplOptions
.Synchronized
)]
792 public override void Write(char[]? buffer
) => _out
.Write(buffer
);
794 [MethodImpl(MethodImplOptions
.Synchronized
)]
795 public override void Write(char[] buffer
, int index
, int count
) => _out
.Write(buffer
, index
, count
);
797 [MethodImpl(MethodImplOptions
.Synchronized
)]
798 public override void Write(ReadOnlySpan
<char> buffer
) => _out
.Write(buffer
);
800 [MethodImpl(MethodImplOptions
.Synchronized
)]
801 public override void Write(bool value) => _out
.Write(value);
803 [MethodImpl(MethodImplOptions
.Synchronized
)]
804 public override void Write(int value) => _out
.Write(value);
806 [MethodImpl(MethodImplOptions
.Synchronized
)]
807 public override void Write(uint value) => _out
.Write(value);
809 [MethodImpl(MethodImplOptions
.Synchronized
)]
810 public override void Write(long value) => _out
.Write(value);
812 [MethodImpl(MethodImplOptions
.Synchronized
)]
813 public override void Write(ulong value) => _out
.Write(value);
815 [MethodImpl(MethodImplOptions
.Synchronized
)]
816 public override void Write(float value) => _out
.Write(value);
818 [MethodImpl(MethodImplOptions
.Synchronized
)]
819 public override void Write(double value) => _out
.Write(value);
821 [MethodImpl(MethodImplOptions
.Synchronized
)]
822 public override void Write(decimal value) => _out
.Write(value);
824 [MethodImpl(MethodImplOptions
.Synchronized
)]
825 public override void Write(string? value) => _out
.Write(value);
827 [MethodImpl(MethodImplOptions
.Synchronized
)]
828 public override void Write(StringBuilder
? value) => _out
.Write(value);
830 [MethodImpl(MethodImplOptions
.Synchronized
)]
831 public override void Write(object? value) => _out
.Write(value);
833 [MethodImpl(MethodImplOptions
.Synchronized
)]
834 public override void Write(string format
, object? arg0
) => _out
.Write(format
, arg0
);
836 [MethodImpl(MethodImplOptions
.Synchronized
)]
837 public override void Write(string format
, object? arg0
, object? arg1
) => _out
.Write(format
, arg0
, arg1
);
839 [MethodImpl(MethodImplOptions
.Synchronized
)]
840 public override void Write(string format
, object? arg0
, object? arg1
, object? arg2
) => _out
.Write(format
, arg0
, arg1
, arg2
);
842 [MethodImpl(MethodImplOptions
.Synchronized
)]
843 public override void Write(string format
, object?[] arg
) => _out
.Write(format
, arg
);
845 [MethodImpl(MethodImplOptions
.Synchronized
)]
846 public override void WriteLine() => _out
.WriteLine();
848 [MethodImpl(MethodImplOptions
.Synchronized
)]
849 public override void WriteLine(char value) => _out
.WriteLine(value);
851 [MethodImpl(MethodImplOptions
.Synchronized
)]
852 public override void WriteLine(decimal value) => _out
.WriteLine(value);
854 [MethodImpl(MethodImplOptions
.Synchronized
)]
855 public override void WriteLine(char[]? buffer
) => _out
.WriteLine(buffer
);
857 [MethodImpl(MethodImplOptions
.Synchronized
)]
858 public override void WriteLine(char[] buffer
, int index
, int count
) => _out
.WriteLine(buffer
, index
, count
);
860 [MethodImpl(MethodImplOptions
.Synchronized
)]
861 public override void WriteLine(ReadOnlySpan
<char> buffer
) => _out
.WriteLine(buffer
);
863 [MethodImpl(MethodImplOptions
.Synchronized
)]
864 public override void WriteLine(bool value) => _out
.WriteLine(value);
866 [MethodImpl(MethodImplOptions
.Synchronized
)]
867 public override void WriteLine(int value) => _out
.WriteLine(value);
869 [MethodImpl(MethodImplOptions
.Synchronized
)]
870 public override void WriteLine(uint value) => _out
.WriteLine(value);
872 [MethodImpl(MethodImplOptions
.Synchronized
)]
873 public override void WriteLine(long value) => _out
.WriteLine(value);
875 [MethodImpl(MethodImplOptions
.Synchronized
)]
876 public override void WriteLine(ulong value) => _out
.WriteLine(value);
878 [MethodImpl(MethodImplOptions
.Synchronized
)]
879 public override void WriteLine(float value) => _out
.WriteLine(value);
881 [MethodImpl(MethodImplOptions
.Synchronized
)]
882 public override void WriteLine(double value) => _out
.WriteLine(value);
884 [MethodImpl(MethodImplOptions
.Synchronized
)]
885 public override void WriteLine(string? value) => _out
.WriteLine(value);
887 [MethodImpl(MethodImplOptions
.Synchronized
)]
888 public override void WriteLine(StringBuilder
? value) => _out
.WriteLine(value);
890 [MethodImpl(MethodImplOptions
.Synchronized
)]
891 public override void WriteLine(object? value) => _out
.WriteLine(value);
893 [MethodImpl(MethodImplOptions
.Synchronized
)]
894 public override void WriteLine(string format
, object? arg0
) => _out
.WriteLine(format
, arg0
);
896 [MethodImpl(MethodImplOptions
.Synchronized
)]
897 public override void WriteLine(string format
, object? arg0
, object? arg1
) => _out
.WriteLine(format
, arg0
, arg1
);
899 [MethodImpl(MethodImplOptions
.Synchronized
)]
900 public override void WriteLine(string format
, object? arg0
, object? arg1
, object? arg2
) => _out
.WriteLine(format
, arg0
, arg1
, arg2
);
902 [MethodImpl(MethodImplOptions
.Synchronized
)]
903 public override void WriteLine(string format
, object?[] arg
) => _out
.WriteLine(format
, arg
);
906 // On SyncTextWriter all APIs should run synchronously, even the async ones.
909 [MethodImpl(MethodImplOptions
.Synchronized
)]
910 public override ValueTask
DisposeAsync()
916 [MethodImpl(MethodImplOptions
.Synchronized
)]
917 public override Task
WriteAsync(char value)
920 return Task
.CompletedTask
;
923 [MethodImpl(MethodImplOptions
.Synchronized
)]
924 public override Task
WriteAsync(string? value)
927 return Task
.CompletedTask
;
930 [MethodImpl(MethodImplOptions
.Synchronized
)]
931 public override Task
WriteAsync(StringBuilder
? value, CancellationToken cancellationToken
= default)
933 if (cancellationToken
.IsCancellationRequested
)
935 return Task
.FromCanceled(cancellationToken
);
939 return Task
.CompletedTask
;
942 [MethodImpl(MethodImplOptions
.Synchronized
)]
943 public override Task
WriteAsync(char[] buffer
, int index
, int count
)
945 Write(buffer
, index
, count
);
946 return Task
.CompletedTask
;
949 [MethodImpl(MethodImplOptions
.Synchronized
)]
950 public override Task
WriteAsync(ReadOnlyMemory
<char> buffer
, CancellationToken cancellationToken
= default)
952 if (cancellationToken
.IsCancellationRequested
)
954 return Task
.FromCanceled(cancellationToken
);
958 return Task
.CompletedTask
;
961 [MethodImpl(MethodImplOptions
.Synchronized
)]
962 public override Task
WriteLineAsync(ReadOnlyMemory
<char> buffer
, CancellationToken cancellationToken
= default)
964 if (cancellationToken
.IsCancellationRequested
)
966 return Task
.FromCanceled(cancellationToken
);
969 WriteLine(buffer
.Span
);
970 return Task
.CompletedTask
;
973 [MethodImpl(MethodImplOptions
.Synchronized
)]
974 public override Task
WriteLineAsync(char value)
977 return Task
.CompletedTask
;
980 [MethodImpl(MethodImplOptions
.Synchronized
)]
981 public override Task
WriteLineAsync()
984 return Task
.CompletedTask
;
987 [MethodImpl(MethodImplOptions
.Synchronized
)]
988 public override Task
WriteLineAsync(string? value)
991 return Task
.CompletedTask
;
994 [MethodImpl(MethodImplOptions
.Synchronized
)]
995 public override Task
WriteLineAsync(StringBuilder
? value, CancellationToken cancellationToken
= default)
997 if (cancellationToken
.IsCancellationRequested
)
999 return Task
.FromCanceled(cancellationToken
);
1003 return Task
.CompletedTask
;
1006 [MethodImpl(MethodImplOptions
.Synchronized
)]
1007 public override Task
WriteLineAsync(char[] buffer
, int index
, int count
)
1009 WriteLine(buffer
, index
, count
);
1010 return Task
.CompletedTask
;
1013 [MethodImpl(MethodImplOptions
.Synchronized
)]
1014 public override Task
FlushAsync()
1017 return Task
.CompletedTask
;