好几天以来,这一直困扰着我,而我终于把它归结为一个简单的,可重现的问题。
我有一个NUnit测试项目,它是.NET Core 2.1。它引用了一个.NET Standard 2.0库(我们称之为“ Core”)。
在我的测试项目中:
[TestCase(true, false)]
[TestCase(false, false)]
[TestCase(false, true)]
public void ShouldStartWith(bool useInternal, bool passStartsWith)
{
var result = useInternal ? StartsWithQ("¿Que?") : StringUtilities.StartsWithQ("¿Que?", passStartsWith ? "¿" : null);
result.ShouldBeTrue();
}
public static bool StartsWithQ(string s)
{
return _q.Any(q => s.StartsWith(q, StringComparison.InvariantCultureIgnoreCase));
}
以及Core
类的StringUtilities
项目中
public static bool StartsWithQ(string s, string startsWith = null)
{
return startsWith == null
? _q.Any(q => s.StartsWith(q, StringComparison.InvariantCultureIgnoreCase))
: s.StartsWith(startsWith, StringComparison.InvariantCultureIgnoreCase);
}
两个类均定义了特殊字符列表:
private static readonly List<string> _q = new List<string>
{
"¡",
"¿"
};
在Windows环境中,所有测试用例均通过。但是,当在Linux环境中运行相同的测试时,测试用例ShouldStartWith(False,False)
将失败!
这意味着当测试项目中的所有内容都在运行时,字符串比较可以正常工作,即使将特殊字符传递给StringUtilities
方法,该比较也可以正常工作。但是,当您与在Core项目中编译的字符串进行比较时,特殊字符不再等效!
有人知道这是为什么吗?这是.NET错误吗?如何解决呢?
答案 0 :(得分:0)
您的源文件的编码很可能彼此不匹配和/或与编译器设置不匹配。
示例:
包含public void ShouldStartWith(bool useInternal, bool passStartsWith)
的源文件可以使用utf-8进行编码,而带有列表的源文件则使用Latin-1(或类似语言)进行编码。
当我们通过以下方式播放时:
¿
的utf-8表示形式为:0xC2 0xBF
。¿
的Latin-1表示为:0xBF
。因此,当编译器将您的源文件解释为Latin-1时,那么在保存utf-8的情况下,他将读取2个字节(根据Latin-1也为2个字符),因此无法与字符串。
如评论中所述:克服此问题的最佳方法是使用编译器等待的编码方式对源文件进行编码。
将操作系统排除为错误源的另一种方法:将已编译的项目(DLL的-不要在另一操作系统上重新编译源代码)从一个操作系统复制到另一个操作系统并执行代码。您应该在两个操作系统上看到具有相同二进制编译器输出的相同行为。