Начинается с изменения в Windows Server 2012

Изменить: я изначально думал, что это связано с .NET Framework 4.5. Оказалось, что это относится и к .NET Framework 4.0.

В Windows Server 2012 есть изменения в обработке строк, которые я пытаюсь понять лучше. Кажется, что поведение StartsWith изменилось. Эта проблема воспроизводима с использованием .NET Framework 4.0 и 4.5.

На платформе .NET Framework 4.5 в Windows 7 приведенная ниже программа выводит «False, t». На Windows 2012 Server вместо этого выводится «True, t».

internal class Program
{
   private static void Main(string[] args)
   {
      string byteOrderMark = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
      Console.WriteLine("test".StartsWith(byteOrderMark));
      Console.WriteLine("test"[0]);
   }
}

Другими словами, StartsWith (ByteOrderMark) возвращает true независимо от содержимого строки. Если у вас есть код, который пытается убрать метку порядка байтов, используя следующий метод, этот код будет хорошо работать в Windows 7, но будет печатать «est» в Windows 2012.

internal class Program
{
  private static void Main(string[] args)
  {
     string byteOrderMark = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
     string someString = "Test";

     if (someString.StartsWith(byteOrderMark))
        someString = someString.Substring(1);

     Console.WriteLine("{0}", someString);
     Console.ReadKey();

  }

}

Я понимаю, что вы уже сделали что-то не так, если в строке есть маркеры порядка байтов, но мы интегрируемся с устаревшим кодом, который имеет это. Я знаю, что могу решить эту конкретную проблему, выполнив что-то вроде ниже, но я хочу лучше понять проблему.

someString = someString.Trim(byteOrderMark[0]);

Ханс Пассант предложил использовать конструктор UTF8Encoding, который позволяет мне явно указать идентификатор UTF8. Я пробовал это, но это дает тот же результат. Приведенный ниже код отличается в выходных данных между Windows 7 и Windows Server 2012. В Windows 7 выводится «Результат: Ложь». В Windows Server 2012 выводится «Результат: Истина».

  private static void Main(string[] args)
  {
     var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
     string byteOrderMark = encoding.GetString(encoding.GetPreamble());
     Console.WriteLine("Result: " + "Hello".StartsWith(byteOrderMark));
     Console.ReadKey();
  }

Я также попробовал следующий вариант, который печатает False, False, False в Windows 7, но True, True, False в Windows Server 2012, что подтверждает, что оно связано с реализацией StartsWith в Windows Server 2012.

  private static void Main(string[] args)
  {
     var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
     string byteOrderMark = encoding.GetString(encoding.GetPreamble());
     Console.WriteLine("Hello".StartsWith(byteOrderMark));
     Console.WriteLine("Hello".StartsWith('\ufeff'.ToString()));
     Console.WriteLine("Hello"[0] == '\ufeff');

     Console.ReadKey();
  }

Ответы на вопрос(1)

Ваш ответ на вопрос