Обратить строку с акцентом?

Итак, я увидел Jon skeet видео и был пример кода:

Должна была быть проблема с é - после реверсирования, но я думаю, что она терпит неудачу на .net2 (IMHO), в любом случае это сработало для меня, и я видел правильную строку в обратном порядке.

char[] a="Les Misérables".ToCharArray();
Array.Reverse(a);
string n= new string(a);
Console.WriteLine (n); //selbarésiM seL

Но я понял:

На иврите есть "Алеф" char: א

и я могу добавить знаки препинания как: אֳ (который, я считаю, состоит из 2 символов, но пока отображается как один.)

Но посмотрим, что получится:

char[] a="Les Misאֳrables".ToCharArray();
Array.Reverse(a);
string n= new string(a);
Console.WriteLine (n); //selbarֳאsiM seL

Был раскол...

Я могу понять, почему это происходит:

Console.WriteLine ("אֳ".Length); //2

Так что мне было интересно, если обходной путь для такого рода проблем в С# (или мне нужно создать собственный механизм...)

Ответ 1

Проблема заключается в том, что Array.Reverse не знает, что определенные последовательности значений char могут объединяться, чтобы сформировать один символ или "grapheme" и, следовательно, не должны быть отменены. Вы должны использовать что-то, что понимает Unicode, объединяющее последовательности символов, например TextElementEnumerator:

// using System.Globalization;

TextElementEnumerator enumerator =
    StringInfo.GetTextElementEnumerator("Les Misאֳrables");

List<string> elements = new List<string>();
while (enumerator.MoveNext())
    elements.Add(enumerator.GetTextElement());

elements.Reverse();
string reversed = string.Concat(elements);  // selbarאֳsiM seL

Ответ 2

Если вы сделали расширение

public static IEnumerable<string> ToTextElements(this string source)
{
    var e = StringInfo.GetTextElementEnumerator(source)
    while (e.MoveNext())
    {
        yield return e.GetTextElement();
    }
}

вы могли бы сделать,

const string a = "AnyStringYouLike";
var aReversed = string.Concat(a.ToTextElements().Reverse());