在Windows Server 2012中启动更改

编辑:我原本以为这与.NET Framework 4.5有关。 原来它也适用于.NET Framework 4.0。

Windows Server 2012中的字符串处理方式发生了变化,我试图更好地理解它。 似乎StartsWith的行为已经改变。 使用.NET Framework 4.0和4.5可以重现该问题。

使用Windows 7上的.NET Framework 4.5,下面的程序打印“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上正常工作,但将在Windows 2012上打印“est”。

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

}

我知道如果你在字符串中有字节顺序标记,你已经做错了,但我们正在与具有此function的遗留代码集成。 我知道我可以通过以下方式解决这个具体问题,但我想更好地理解这个问题。

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

Hans Passsant建议使用UTF8Encoding的构造函数,它允许我明确地告诉它发出UTF8标识符。 我尝试了这个,但它给出了相同的结果。 以下代码在Windows 7和Windows Server 2012之间的输出不同。在Windows 7上,它打印“Result:False”。 在Windows Server 2012上,它打印“Result:True”。

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

我还尝试了以下变体,它在Windows 7上打印False,False,False但在Windows Server 2012上打印为True,True,False,这证实它与Windows Server 2012上StartsWith的实现有关。

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

事实certificate,我可以重复这一点,在Windows 8.1上运行测试程序。 它与Server 2012属于同一个“家庭”。

最可能的问题来源是文化敏感的比较规则已经改变。 它们可能是,呃, 片状,并且可能对这些角色产生奇怪的结果。 BOM是零宽度空间。 推理这个需要与理解为什么“abc”同样的心理体操.StartsWith(“”)返回true 🙂

您需要使用StringComparison.Ordinal解决您的问题。 这产生了假,假,假:

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