C#中的字符串等价需要编码匹配吗?

时间:2014-05-01 14:05:35

标签: c# xml encoding literals

我几天来一直在努力解决问题并且终于解决了出了什么问题,但我只能在StackOverflow(等)上找到矛盾的答案,所以想要问一下什么是解释继续

例如this link(与许多其他参考for example this one一样,或者Jon Skeet herehere关于该主题的这些看似参考的参考文献表明“C#中的字符串总是UTF-16 [Unicode?],没有办法”转换“它。只要你在内存中操作字符串,编码就无关紧要了,只有你把字符串写入一个流才重要(文件,内存流,网络流......)。“

我为了演示我的问题而构建的大大简化的测试用例如下所示,它可能不是复制粘贴可复制的,因为它依赖于某些字符串具有不同的编码,但请相信我测试通过写入。我正在使用VS2012 Update 4。

奇怪的是,以下两行通过。

Assert.IsFalse(copiedFromXmlDoubleQuote == copiedFromXmlEscapedQuote);
Assert.AreNotEqual(copiedFromXmlDoubleQuote, copiedFromXmlEscapedQuote);

相同的字符串无法等效,因为它们的编码方式不同(copiedFromXmlDoubleQuote 在编辑器中将\替换为“)。

所有这些都表明Visual Studio编辑器可识别编码,并且代码声明的字符串也可识别编码。我的问题是,如果我做了一些愚蠢的事情,或者任何人都可以同意我的发现,如果可能的话,请参考我的内容,以帮助澄清字符串编码等同的故事... 因为我将要工作在Xml世界中,最好的做法是在反序列化时将所有内容显式转换为Unicode,并在再次序列化时根据需要重新编码?

[TestMethod]
public void EscapedCharacterDoesNotEqualLiteralString()
{
  string actual = "\"";
  Assert.AreEqual("\"", actual);
  Assert.AreEqual(@"""", actual);
  string typedEscapedQuote = "<?xml version=\"1.0\" encoding=\"utf-16\"?>";
  string typedDoubleQuote = @"<?xml version=""1.0"" encoding=""utf-16""?>";
  Assert.IsTrue(typedDoubleQuote == typedEscapedQuote);
  Assert.AreEqual(typedDoubleQuote, typedEscapedQuote);
  string copiedFromXmlEscapedQuote = "<?xml version=\"1.0\" encoding=\"utf-16\"?>";
  string copiedFromXmlDoubleQuote = @"<?xml version=""1.0"" encoding=""utf-16""?>";
  Assert.IsFalse(copiedFromXmlDoubleQuote == copiedFromXmlEscapedQuote);
  Assert.AreNotEqual(copiedFromXmlDoubleQuote, copiedFromXmlEscapedQuote);
  Assert.IsTrue(copiedFromXmlDoubleQuote.ToUnicode() == copiedFromXmlEscapedQuote.ToUnicode());
  Assert.AreEqual(copiedFromXmlDoubleQuote.ToUnicode(), copiedFromXmlEscapedQuote.ToUnicode());
}

private static string BytesToString(byte[] bytes, Encoding encoding)
{
  using (MemoryStream ms = new MemoryStream(bytes))
  {
    using (StreamReader sr = new StreamReader(ms, encoding))
    {
      string s = sr.ReadToEnd();
      sr.Close();
      return s;
    }
  }
}

public static string ToUnicode(this string s)
{
  return BytesToString(new UnicodeEncoding().GetBytes(s), Encoding.Unicode);
}

我已经在zip here

中加载了一个示例Vs2012 sln

1 个答案:

答案 0 :(得分:2)

我对您的ZIP文件的初步检查显示

   static string copiedFromXmlEscapedQuote = "<?xml version=\"1.0\" encoding=\"utf-16\"?>";
   static string copiedFromXmlDoubleQuote = @"<?xml version=""1.0"" encoding=""utf-16""?>";

   ? copiedFromXmlEscapedQuote.Length
   39
   ? copiedFromXmlDoubleQuote.Length
   40

.net框架中对字符串等价的第一次检查是长度检查 - 如果字符串长度不同,它就不会检查内容。

进一步检查;

 ? copiedFromXmlDoubleQuote.Last()
   62 '>'
   ? copiedFromXmlEscapedQuote.Last()
   62 '>'
   ? copiedFromXmlEscapedQuote.First()
   60 '<'
   ? copiedFromXmlDoubleQuote.First()
   65279 ''

所以它的第一个字符是不同的。本文介绍了65279的值。 What is this char? 65279 ''

看起来你是对的 - 它是VS.net编辑器,它保留了BOM char,在二进制编辑器中打开程序文件显示这些是不同的,所以我猜测在VS中使用@ .net告诉编译器使用不同的编码器打开以下字节。