using System.Collections.Generic;
using System.Globalization;
public static partial class TextHelper
public static string ToUtf8HexValues(this string s)
Span<byte> runeByteSpan = stackalloc byte[4];
Span<char> charSpan = stackalloc char[2];
var sb = new StringBuilder();
foreach (var rune in s.EnumerateRunes())
for (int i = 0, length = rune.EncodeToUtf8(runeByteSpan); i < length; i++)
if (runeByteSpan[i].TryFormat(charSpan, out var n, "X"))
sb.Append(charSpan.Slice(0, n));
public static partial class TextHelper
public static IEnumerable<ReadOnlyMemory<char>> TextElements(this string s) => (s ?? "").AsMemory().TextElements();
public static IEnumerable<ReadOnlyMemory<char>> TextElements(this ReadOnlyMemory<char> s)
for (int index = 0, length = StringInfo.GetNextTextElementLength(s.Span);
index += length, length = StringInfo.GetNextTextElementLength(s.Span.Slice(index)))
yield return s.Slice(index, length);
public static string ToUtf8GraphemeHexValues(this string s)
Span<byte> runeByteSpan = stackalloc byte[4];
Span<char> charSpan = stackalloc char[2];
var sb = new StringBuilder();
foreach (var chunk in s.TextElements())
foreach (var rune in chunk.Span.EnumerateRunes())
for (int i = 0, length = rune.EncodeToUtf8(runeByteSpan); i < length; i++)
if (runeByteSpan[i].TryFormat(charSpan, out var n, "X"))
sb.Append(charSpan.Slice(0, n));
public static void Main()
var input2 = "$£€𐍈𝐀\u0302";
var s2 = input2.ToUtf8GraphemeHexValues();
Console.WriteLine($"{input2}.ToUtf8GraphemeHexValues() = {s2}");
Assert.That(s2 == "24 C2A3 E282AC F0908D88 F09D9080CC82");
Assert.That(s2 != input2.ToUtf8HexValues());
var s1 = input1.ToUtf8HexValues();
Console.WriteLine($"\n{input1}.ToUtf8HexValues() = {s1}");
Assert.That(s1 == "24 C2A3 E282AC F0908D88");
Assert.That(s1 == input1.ToUtf8GraphemeHexValues());
var s3 = input3.ToUtf8GraphemeHexValues();
Console.WriteLine($"\n{input3}.ToUtf8GraphemeHexValues() = {s3}");
Assert.That(!s3.Contains(" "));
var s4 = input4.ToUtf8GraphemeHexValues();
Console.WriteLine($"\n{input4}.ToUtf8GraphemeHexValues() = {s4}");
Assert.That(s4 == "F0908D88");
var s5 = input5.ToUtf8GraphemeHexValues();
Console.WriteLine($"\n{input5}.ToUtf8GraphemeHexValues() = {s5}");
Assert.That(s5 == "F0908D88 20 EFB7BD");