Comienza con cambio en Windows Server 2012

Edición: originalmente pensé que esto estaba relacionado con .NET Framework 4.5. Resultó que se aplica a .NET Framework 4.0 también.

Hay un cambio en la forma en que se manejan las cadenas en Windows Server 2012 que estoy tratando de entender mejor. Parece que el comportamiento de StartsWith ha cambiado. El problema es reproducible utilizando .NET Framework 4.0 y 4.5.

Con .NET Framework 4.5 en Windows 7, el siguiente programa imprime "False, t". En Windows 2012 Server, imprime "True, t" en su lugar.

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]);
   }
}

En otras palabras, StartsWith (ByteOrderMark) devuelve verdadero independientemente del contenido de la cadena. Si tiene un código que intenta eliminar la marca de orden de bytes utilizando el siguiente método, este código funcionará bien en Windows 7 pero se imprimirá "est" en 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();

  }

}

Me doy cuenta de que ya has hecho algo mal si tienes marcadores de orden de bytes en una cadena, pero nos estamos integrando con el código heredado que tiene esto. Sé que puedo resolver este problema específico haciendo algo como a continuación, pero quiero entender mejor el problema.

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

Hans Passsant sugirió usar el constructor de UTF8Encoding que me permite indicarlo explícitamente para que emita el identificador UTF8. Intenté esto, pero da el mismo resultado. El siguiente código difiere en la salida entre Windows 7 y Windows Server 2012. En Windows 7, imprime "Resultado: Falso". En Windows Server 2012 imprime "Resultado: Verdadero".

  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();
  }

También probé la siguiente variante, que imprime Falso, Falso, Falso en Windows 7 pero Verdadero, Verdadero, Falso en Windows Server 2012, lo que confirma que está relacionado con la implementación de StartsWith en 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();
  }

Respuestas a la pregunta(1)

Su respuesta a la pregunta