Неоднозначность поиска строк в Dotnet (netcore31 против net47 против roslyn)

#c# #.net #string-search

#c# #.net #поиск по строке

Вопрос:

Я обнаружил, что в некоторых случаях строка.indexOf() возвращает -1 при поиске двойного разрыва строки r n r n, когда за ним следует последовательность байтов 0xCC (204) (могут быть и другие, не проверял). Ниже приведен пример dotnetfiddle — там можно выбрать компилятор. В компиляторе netcore31 строка найдена всегда, в других компиляторах только тогда, когда за ней не следует последовательность 0xCC. Кто-нибудь может это объяснить?

https://dotnetfiddle.net/ZMW7tL

РЕДАКТИРОВАТЬ: То же самое происходит, когда я ставлю 0xCB или 0xCD после last r n.

Исходный код скрипки:

 using System;
                
public class Program
{
    public static void Main()
    {
        var x = new byte[] { 99, 108, 111, 115, 101, 13, 10, 13, 10, 204, 159, 67, 4 };
        var z = System.Text.Encoding.UTF8.GetString(x);
        Console.WriteLine(z);
        Console.WriteLine();
        var idx = z.IndexOf("rnrn");
        Console.WriteLine("index = "   idx);
        Console.WriteLine("=========================");
 
        var x1 = new byte[] { 99, 108, 111, 115, 101, 13, 10, 13, 10, 5, 159, 67, 4 };
        var z1 = System.Text.Encoding.UTF8.GetString(x1);
        Console.WriteLine(z1);
        Console.WriteLine();
        var idx1 = z1.IndexOf("rnrn");
        Console.WriteLine("index modified = "   idx1);
        Console.WriteLine("=========================");
 
        var x2 = new byte[] { 13, 10, 13, 10, 204, 159 };
        var z2 = System.Text.Encoding.UTF8.GetString(x2);
        Console.WriteLine(z2);
        Console.WriteLine();
        var idx2 = z2.IndexOf("rnrn");
        Console.WriteLine("index short = "   idx2);
    }
}
  

Комментарии:

1. Я собираюсь предположить, что это из-за проблемы с кодировкой. У вас есть массив байтов, которые декодируются в a string , но 204 не является стандартным ASCII и поэтому для преобразования его в a будет использоваться кодировка char .

2. @Neil Я понимаю, что это не символ ASCII, но я бы ожидал, что .net проанализирует входящую строку «слева направо», и как только соответствующая подстрока найдена, возвращается ее индекс, независимо от последующих символов. Я знаю, что различные кодировки обрабатывают последовательности байтов по-разному, но я не могу точно понять, почему приведенный выше пример не работает. Итак, я ищу более подробное объяснение.

3. Допустимый UTF-8. Символ (закодированный в виде двух байт в UTF-8) представляет собой комбинирующий символ, который объединяется с символом, предшествующим ему, так что у вас есть n с объединением ниже. .NET Framework сравнивает объединенный символ, а не отдельные кодовые точки.

4. Хорошо, вероятно, это: utf8-chartable.de /…

5. Да, те. И даже это не полные «символы», а просто кодовые точки Unicode, которые объединяются с другими кодовыми точками для создания символов.