Add more comments to StringBuilder.EnumerateChunks()
authorVance Morrison <vancemorrison@comcast.net>
Wed, 23 May 2018 21:03:16 +0000 (14:03 -0700)
committerVance Morrison <vancemorrison@comcast.net>
Wed, 23 May 2018 21:03:16 +0000 (14:03 -0700)
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

src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs

index a06ccee..58af600 100644 (file)
@@ -565,10 +565,17 @@ namespace System.Text
         ///      foreach (ReadOnlyMemory<char> 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<char> chunk in sb.EnumerateChunks())
         ///    {
@@ -587,6 +594,10 @@ namespace System.Text
         /// </summary>
         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)
+
             /// <summary>
             /// Implement IEnumerable.GetEnumerator() to return  'this' as the IEnumerator  
             /// </summary>
@@ -651,6 +662,9 @@ namespace System.Text
             /// </summary>
             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
         }