浏览代码

Fix Cell.Grapheme validation allocation by adding GetGraphemeCount

Added allocation-free grapheme counting to GraphemeHelper:
- New GetGraphemeCount() method counts graphemes without materializing array
- Uses TextElementEnumerator directly, avoiding .ToArray() allocation
- Updated Cell.Grapheme setter to use GetGraphemeCount() instead of .ToArray().Length

Impact: Eliminates allocation on every Cell.Grapheme property set
- Validation now happens without intermediate array allocation
- Particularly beneficial for cell-based operations and grid rendering

All unit tests pass (12,055 parallelizable + 1,173 non-parallel)

Co-authored-by: tig <[email protected]>
copilot-swe-agent[bot] 1 周之前
父节点
当前提交
12756a29d8
共有 2 个文件被更改,包括 24 次插入1 次删除
  1. 1 1
      Terminal.Gui/Drawing/Cell.cs
  2. 23 0
      Terminal.Gui/Drawing/GraphemeHelper.cs

+ 1 - 1
Terminal.Gui/Drawing/Cell.cs

@@ -27,7 +27,7 @@ public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, st
         readonly get => _grapheme;
         set
         {
-            if (GraphemeHelper.GetGraphemes(value).ToArray().Length > 1)
+            if (GraphemeHelper.GetGraphemeCount (value) > 1)
             {
                 throw new InvalidOperationException ($"Only a single {nameof (Grapheme)} cluster is allowed per Cell.");
             }

+ 23 - 0
Terminal.Gui/Drawing/GraphemeHelper.cs

@@ -46,4 +46,27 @@ public static class GraphemeHelper
             yield return element;
         }
     }
+
+    /// <summary>
+    ///     Counts the number of grapheme clusters in a string without allocating intermediate collections.
+    /// </summary>
+    /// <param name="text">The string to count graphemes in.</param>
+    /// <returns>The number of grapheme clusters, or 0 if the string is null or empty.</returns>
+    public static int GetGraphemeCount (string text)
+    {
+        if (string.IsNullOrEmpty (text))
+        {
+            return 0;
+        }
+
+        TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator (text);
+        var count = 0;
+
+        while (enumerator.MoveNext ())
+        {
+            count++;
+        }
+
+        return count;
+    }
 }