From: Vance Morrison Date: Wed, 23 May 2018 21:03:16 +0000 (-0700) Subject: Add more comments to StringBuilder.EnumerateChunks() X-Git-Tag: submit/tizen/20210909.063632~11030^2~4766^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1f9566dbc1f100f66ac3f30504d847e7d3176544;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Add more comments to StringBuilder.EnumerateChunks() This does not change execution of the code (only comments, placement) Added a warning about modifying the stringbuilder while enumerating. Commit migrated from https://github.com/dotnet/coreclr/commit/c6409334f6fc56884bb7df91489293d52efaabd1 --- diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs index a06ccee..58af600 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -565,10 +565,17 @@ namespace System.Text /// foreach (ReadOnlyMemory chunk in sb.EnumerateChunks()) /// foreach(char c in chunk.Span) /// { /* operation on c } - /// - /// Note that creating a ReadOnlySpan from a ReadOnlyMemory is expensive compared to the - /// fetching of the character, so create a local variable for the SPAN if you need to use - /// a for statement for example + /// + /// It is undefined what happens if the StringBuilder is modified while the chunk + /// enumeration is incomplete. StringBuilder is also not thread-safe, so operating + /// on it with concurrent threads is illegal. Finally the ReadOnlyMemory chunks returned + /// are NOT guarenteed to remain unchanged if the StringBuilder is modified, so do + /// not cache them for later use either. This API's purpose is efficiently extracting + /// the data of a CONSTANT StringBuilder. + /// + /// Creating a ReadOnlySpan from a ReadOnlyMemory (the .Span property) is expensive + /// compared to the fetching of the character, so create a local variable for the SPAN + /// if you need to use it in a nested for statement. For example /// /// foreach (ReadOnlyMemory chunk in sb.EnumerateChunks()) /// { @@ -587,6 +594,10 @@ namespace System.Text /// public struct ChunkEnumerator { + private readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string) + private StringBuilder _currentChunk; // The chunk that this enumerator is currently returning (Current). + private readonly ManyChunkInfo _manyChunks; // Only used for long string builders with many chunks (see constructor) + /// /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator /// @@ -651,6 +662,9 @@ namespace System.Text /// private class ManyChunkInfo { + private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first) + private int _chunkPos; + public bool MoveNext(ref StringBuilder current) { int pos = ++_chunkPos; @@ -671,14 +685,7 @@ namespace System.Text } _chunkPos = -1; } - - readonly StringBuilder[] _chunks; // These are in normal order (first chunk first) - int _chunkPos; } - - readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string) - StringBuilder _currentChunk; // The chunk that this enumerator is currently returning (Current). - readonly ManyChunkInfo _manyChunks; // Only used for long string builders with many chunks (see constructor) #endregion }