string.Format返回的.NET字符串中的空格与源代码中声明的空格不匹配 - 多个表示形式?

Mar*_*rek 2 .net c# string

string.Format返回的字符串似乎使用了一些奇怪的编码.与源代码中声明的字符串中包含的空格相比,格式字符串中包含的空格使用不同的字节值表示.

以下测试用例演示了该问题:

[Test]
public void FormatSize_Regression() 
{
  string size1023 = FileHelper.FormatSize(1023);
  Assert.AreEqual("1 023 Bytes", size1023);
}
Run Code Online (Sandbox Code Playgroud)

失败:

    String lengths are both 11. Strings differ at index 1.
    Expected: "1 023 Bytes"
    But was:  "1 023 Bytes"
    ------------^

FormatSize方法:

public static string FormatSize(long size) 
{
  if (size < 1024)
     return string.Format("{0:N0} Bytes", size);
  else if (size < 1024 * 1024)
     return string.Format("{0:N2} KB", (double)((double)size / 1024));
  else
     return string.Format("{0:N2} MB", (double)((double)size / (1024 * 1024)));
}
Run Code Online (Sandbox Code Playgroud)

在Assert行上设置断点时从VS立即窗口:

size1023
"1 023 Bytes"

System.Text.Encoding.UTF8.GetBytes(size1023)
{byte[12]}
    [0]: 49
    [1]: 194 <--------- space is 194/160 here? Unicode bytes indicate that space should be the 160. What is the 194 then?
    [2]: 160
    [3]: 48
    [4]: 50
    [5]: 51
    [6]: 32
    [7]: 66
    [8]: 121
    [9]: 116
    [10]: 101
    [11]: 115
System.Text.Encoding.UTF8.GetBytes("1 023 Bytes")
{byte[11]}
    [0]: 49
    [1]: 32  <--------- space is 32 here
    [2]: 48
    [3]: 50
    [4]: 51
    [5]: 32
    [6]: 66
    [7]: 121
    [8]: 116
    [9]: 101
    [10]: 115

System.Text.Encoding.Unicode.GetBytes(size1023)
{byte[22]}
    [0]: 49
    [1]: 0
    [2]: 160 <----------- 160,0 here
    [3]: 0
    [4]: 48
    [5]: 0
    [6]: 50
    [7]: 0
    [8]: 51
    [9]: 0
    [10]: 32
    [11]: 0
    [12]: 66
    [13]: 0
    [14]: 121
    [15]: 0
    [16]: 116
    [17]: 0
    [18]: 101
    [19]: 0
    [20]: 115
    [21]: 0
System.Text.Encoding.Unicode.GetBytes("1 023 Bytes")
{byte[22]}
    [0]: 49
    [1]: 0
    [2]: 32 <----------- 32,0 here
    [3]: 0
    [4]: 48
    [5]: 0
    [6]: 50
    [7]: 0
    [8]: 51
    [9]: 0
    [10]: 32
    [11]: 0
    [12]: 66
    [13]: 0
    [14]: 121
    [15]: 0
    [16]: 116
    [17]: 0
    [18]: 101
    [19]: 0
    [20]: 115
    [21]: 0
Run Code Online (Sandbox Code Playgroud)

问题:这怎么可能?

Jon*_*eet 12

我怀疑你当前的文化正在使用一个有趣的"千位"分隔符--U + 00A0,这是一个不间断的空格字符.这不是一个完全不合理的千位分隔符,说实话......这意味着你不应该得到这样的文字显示:

The size of the file is 1
023 bytes.
Run Code Online (Sandbox Code Playgroud)

相反,你会得到

The size of the file is
1 023 bytes.
Run Code Online (Sandbox Code Playgroud)

在我的盒子上,我得到了"1,023".您希望您的FormatSize方法使用当前文化还是特定文化?如果它是当前的文化,你应该让你的单元测试指定文化.我有几个用于此的包装器方法:

internal static void WithInvariantCulture(Action action)
{
    WithCulture(CultureInfo.InvariantCulture, action);
}

internal static void WithCulture(CultureInfo culture, Action action)
{
    CultureInfo original = Thread.CurrentThread.CurrentCulture;
    try
    {
        Thread.CurrentThread.CurrentCulture = culture;
        action();
    }
    finally
    {
        Thread.CurrentThread.CurrentCulture = original;
    }            
}
Run Code Online (Sandbox Code Playgroud)

所以我可以跑:

WithInvariantCulture(() =>
{
    // Body of test
};
Run Code Online (Sandbox Code Playgroud)

等等

如果你想测试你得到的确切字符串,你可以使用:

Assert.AreEqual("1\u00A0023 Bytes", size1023);
Run Code Online (Sandbox Code Playgroud)