using System.Diagnostics;
using System.Globalization;
public static class Program
const char cEMPTY = '\0';
static readonly string EMPTY = cEMPTY.ToString();
public static string UnicodeReplaceAt(this string str, int offset, char replaceChar)
string replaceBy = replaceChar.ToString();
return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
else if (!string.IsNullOrEmpty(replaceBy))
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
return str.RemoveByTextElements(offset, count);
public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
if (offset > str.LengthInTextElements)
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
offset + count < str.LengthInTextElements
? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
if (offset > str.LengthInTextElements)
if (string.IsNullOrEmpty(str.String))
return new StringInfo(insertStr);
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
public static string SubsituteStringStringBuilder(this string s, int idx, char replaceChar)
if (string.IsNullOrEmpty(s) || idx >= s.Length || idx < 0)
return new StringBuilder(s).Remove(idx, 1).Insert(idx, replaceChar.ToString()).ToString();
public static string ReplaceAtSubstring(this string s, int idx, char replaceChar)
if (string.IsNullOrEmpty(s) || idx >= s.Length || idx < 0)
return s.Substring(0, idx) + replaceChar.ToString() + s.Substring(idx + replaceChar.ToString().Length, s.Length - (idx + replaceChar.ToString().Length));
public static string ReplaceAtStringManipulation(this string s, int idx, char replaceChar)
if (string.IsNullOrEmpty(s) || idx >= s.Length || idx < 0)
return s.Remove(idx, 1).Insert(idx, replaceChar.ToString());
public static string ReplaceAtLinq(this string value, int index, char newchar)
if (value.Length <= index)
return string.Concat(value.Select((c, i) => i == index ? newchar : c));
public static string ReplaceAtCharArray(this string input, uint index, char newChar)
if (string.IsNullOrEmpty(input) || index >= input.Length)
char[] chars = input.ToCharArray();
return new string(chars);
public static void Main()
Console.WriteLine("Unicode String Replace At Issue");
Console.WriteLine("Lets examine string \"πΆπ₯Γ©-\"");
Console.WriteLine("πΆπ₯Γ©- is length of " + "πΆπ₯Γ©-".Length + ", but there are ONLY 4 characters! Why not len=4?");
Console.WriteLine("πΆπ₯ are double byte UNICODE characters (> \\u10000) of width or len 2 each ");
Console.WriteLine("πΆπ₯Γ©- below will replace space after lasting character '-' (position 4) with a sub using most common techniques seen online");
Stopwatch sw = new Stopwatch();
Console.WriteLine("πΆπ₯Γ©- using ReplaceAtCharArray".ReplaceAtCharArray(4, 'X'));
Console.WriteLine("in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("πΆπ₯Γ©- using ReplaceAtLinq".ReplaceAtLinq(4, 'Y'));
Console.WriteLine("in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("πΆπ₯Γ©- using ReplaceAtStringManipulation".ReplaceAtStringManipulation(4, 'Z'));
Console.WriteLine("in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("πΆπ₯Γ©- using ReplaceAtSubstring".ReplaceAtSubstring(4, 'A'));
Console.WriteLine("in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("πΆπ₯Γ©- using SubsituteStringStringBuilder".SubsituteStringStringBuilder(4, 'W'));
Console.WriteLine("in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("πΆπ₯Γ©- using UnicodeReplaceAt".UnicodeReplaceAt(4, '4'));
Console.WriteLine("in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("UnicodeReplaceAt replaces properly at position 4 in zero based index string");
Console.Write("πΆπ₯Γ©- using UnicodeReplaceAt(0, '0')".UnicodeReplaceAt(0, '0'));
Console.WriteLine(" in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.Write("πΆπ₯Γ©- using UnicodeReplaceAt(1, '1')".UnicodeReplaceAt(1, '1'));
Console.WriteLine(" in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.Write("πΆπ₯Γ©- using UnicodeReplaceAt(2, '2')".UnicodeReplaceAt(2, '2'));
Console.WriteLine(" in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.Write("πΆπ₯Γ©- using UnicodeReplaceAt(3, '3')".UnicodeReplaceAt(3, '3'));
Console.WriteLine(" in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.Write("πΆπ₯Γ©- using UnicodeReplaceAt(4, '4')".UnicodeReplaceAt(4, '4'));
Console.WriteLine(" in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.Write("πΆπ₯Γ©-".UnicodeReplaceAt(5, '5')+" using UnicodeReplaceAt(5, '5') - this is beyond end of string, so return orginal string");
Console.WriteLine(" in {0} ticks.", sw.ElapsedTicks.ToString("N0"));
Console.WriteLine("String.Replace works, but replaces all characters, not at specific location as above functions");
Console.Write("πΆπ₯Γ©- using String.Replace".Replace("π₯", "+") + "('π₯', '+')");