C# 在Windows Server 2012中随更改而启动

C# 在Windows Server 2012中随更改而启动,c#,string,unicode,.net-4.5,C#,String,Unicode,.net 4.5,编辑:我最初认为这与.NETFramework4.5有关。事实证明,它也适用于.NETFramework4.0 Windows Server 2012中字符串的处理方式发生了变化,我正试图更好地理解这一点。看来StartsWith的行为已经改变了。该问题可以使用.NET Framework 4.0和4.5复制 在Windows 7上使用.NET Framework 4.5时,下面的程序会打印“False,t”。在Windows 2012服务器上,它会打印“True,t” 换句话说,不管字符串内容

编辑:我最初认为这与.NETFramework4.5有关。事实证明,它也适用于.NETFramework4.0

Windows Server 2012中字符串的处理方式发生了变化,我正试图更好地理解这一点。看来StartsWith的行为已经改变了。该问题可以使用.NET Framework 4.0和4.5复制

在Windows 7上使用.NET Framework 4.5时,下面的程序会打印“False,t”。在Windows 2012服务器上,它会打印“True,t”

换句话说,不管字符串内容如何,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();

  }
}

我意识到,如果字符串中有字节顺序标记,您已经做了一些错误的事情,但我们正在与具有此功能的遗留代码集成。我知道我可以通过做下面的事情来解决这个具体问题,但我想更好地理解这个问题

someString = someString.Trim(byteOrderMark[0]);
Hans Passsant建议使用UTF8Encoding的构造函数,让我显式地告诉它发出UTF8标识符。我试过这个,但结果是一样的。以下代码在Windows 7和Windows Server 2012之间的输出不同。在Windows7上,它打印“结果:False”。在Windows Server 2012上,它打印“结果:真”

我还尝试了以下变体,它在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();
  }
事实证明,我可以重新编程,在Windows8.1上运行测试程序。它与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();
  }
问题最可能的根源是对文化敏感的比较规则发生了变化。他们可能是,呃,古怪的,在这些角色上可能会有奇怪的结果。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();
}

我甚至不会使用
Trim
——如果您只担心第一个字符,那么只需检查
text[0]=='\ufeff'
是否足够好(对空字符串进行适当的处理)。这看起来很奇怪。当然,这比修剪效果好。假设TrimStart也能正常工作。不过,我主要还是想弄明白为什么一开始这种情况发生了变化。该网站上的许多投票支持率较高的回复建议首先使用StartsWith()进行检查,并且当在Windows Server 2012上使用.NET Framework 4.5运行时,代码将崩溃。这里的示例:。事实证明,对于我来说,这个问题在.NET Framework 4.0中也是可以重现的。我根据你的建议更新了我的主要帖子,加入了一个新的代码片段,但它在Windows7和WindowsServer2012之间给出了不同的行为。我还添加了一个代码段,其中我硬编码\ufeff并将其传递给StartWith,并且看到的行为在Windows 7和Windows 2012 Server之间有所不同。我同意这很奇怪,但这正是我看到的。你们救了我的命!顺便说一句,我只需要
string byteOrderMarkUtf8=Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()),然后是关键的
启动(byteOrderMarkUtf8,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();
}