xUnit.net: 为什么这2个等价的测试有不同的结果?

xUnit.net: Why do these 2 equivalent tests have different results?

出于某种原因,此利用 InlineData 的测试在 xUnit 中失败:

[Theory]
[InlineData("\uD800", 1)]
public static void HasLength(string s, int length)
{
    Assert.Equal(length, s.Length);
}

而这个使用 MemberData,通过:

public static IEnumerable<object[]> HasLength_TestData()
{
    yield return new object[] { "\uD800", 1 };
}

[Theory]
[MemberData(nameof(HasLength_TestData))]
public static void HasLength(string s, int length)
{
    Assert.Equal(length, s.Length);
}

这是什么原因?我在 xUnit.net 中发现了错误吗? (我认为这可能与 \uD800 是一个 surrogate character 这一事实有关,并且它在通过 InlineData 时以某种方式被转换为 2 个字符。但不确定为什么。)

不,这不是错误。

如果你想用 UTF-16 表示一个大于 U+FFFF 的值,你需要使用两个 UTF-16 代码单元:一个高代理项(在 0xD800 到 0xDBFF 范围内)后面跟着一个低代理项 (在 0xDC00 到 0xDFFF 范围内)。所以一个高代理人本身是没有意义的。它本身是一个有效的 UTF-16 代码单元,但它只有在后面跟一个低代理项时才有意义。

本文中有更多信息http://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/

Nicolay 的回答没有回答问题,但 link 回答了问题:

属性值使用 UTF-8 存储,孤立的高代理无法从 UTF-16 成功转换。

这是 (VB.NET) LinqPad query 确认情况。