C#:区分 CurrentCulture 和 InvariantCulture 的单元测试
Posted
技术标签:
【中文标题】C#:区分 CurrentCulture 和 InvariantCulture 的单元测试【英文标题】:C#: Unit Test to Differentiate CurrentCulture from InvariantCulture 【发布时间】:2011-04-24 05:52:17 【问题描述】:我有一个采用 StringComparison 参数的方法,它确实需要一个单元测试来证明它正在执行正确的比较类型。
这基本上是我目前所拥有的。它通过比较“oe”和“œ”来区分 Ordinal(参见System.String)。但是,我还没有找到区分 CurrentCulture 和 InvariantCulture 的方法。
using System;
using NUnit.Framework;
using System.Threading;
using System.Globalization;
namespace NUnitTests
[TestFixture]
public class IndexOfTests
[Test]
public void IndexOf_uses_specified_comparison_type()
StringComparison comparisonTypePerformed;
result = TestComparisonType(StringComparison.CurrentCulture);
Assert.AreEqual(StringComparison.CurrentCulture, comparisonTypePerformed);
result = TestComparisonType(StringComparison.InvariantCulture);
Assert.AreEqual(StringComparison.CurrentCulture, comparisonTypePerformed);
result = TestComparisonType(StringComparison.Ordinal);
Assert.AreEqual(StringComparison.CurrentCulture, comparisonTypePerformed);
bool TestComparisonType(StringComparison comparisonType)
int result;
// Ensure the current culture is consistent for test
var prevCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);
try
result = IndexOf("oe", "œ", comparisonType);
if (result == 0)
// The comparison type performed was either CurrentCulture,
// InvariantCulture, or one of the case-insensitive variants.
// TODO: Add test to differentiate between CurrentCulture and InvariantCulture
throw new NotImplementedException();
result = IndexOf("???????", "???????", StringComparison.CurrentCulture);
//...
else // result == -1
// The comparison type performed was either Ordinal or OrdinalIgnoreCase
result = IndexOf("a", "A", StringComparison.CurrentCulture);
if (result)
Console.WriteLine("Comparison type was OrdinalIgnoreCase");
else
Console.WriteLine("Comparison type was Ordinal");
finally
Thread.CurrentThread.CurrentCulture = prevCulture;
我曾考虑通过比较“i”和“I”来使用土耳其语问题,但它仅适用于不区分大小写的比较。
我环顾四周,在字符串相等性测试(仅排序顺序和解析/序列化)中找不到 InvariantCulture 与其他文化不同的情况。例如,根据文化,“ô”和“o”的排序方式不同,但所有文化在相等性测试中返回相同的结果。
是否有用于区分 InvariantCulture 与任何其他文化的平等测试?
编辑: 德语“ß”和“ss”对所有文化都给出相同的结果,因此它们不起作用。
编辑: 实际上,只需要两个字符串在一种文化中相等,而在另一种文化中不相等。
【问题讨论】:
【参考方案1】:CultureInfo 上的 MSDN 示例有一个示例,该示例具有不同的排序顺序,具体取决于文化。我认为这是你最有可能作为起点的赌注。但是,如果这不起作用,您也许可以利用下面的一些信息。
似乎正在String.Compare MSDN 页面上执行一组类似的测试。但在此示例中,它是在 en-US 文化中。
如果您查看 CultureInfo.InvarientCulture 页面,您会注意到 InvarientCulture 基于英语,但没有任何区域或国家/地区编码。 StringComparison 页面提到连字符特别具有不同的权重,具体取决于语言。您可以通过找到一种与英语不同的连字符权重的语言来利用这一点。
***在collation 文章中有一些关于排序的有趣注释,这可能也很有用。通过排序,按字母顺序仔细查看,然后查看西班牙语注释。
例如,29 个字母的字母表 西班牙语将 ñ 视为基本字母 在 n 之后,以前处理过 ch 和 ll 作为 c 之后的基本字母 和 l,分别。 Ch 和 ll 是 仍然被认为是字母,但现在 按字母顺序排列为两个字母 组合。
我不确定这会有多大帮助,但它可能会引导您找到答案。
【讨论】:
谢谢!与不变的文化相比,Ch 和 ll 在某些文化中返回不同的结果。奇怪的是,在西班牙文化中却没有。我发布了一个答案,展示了这些差异,我目前必须将其标记为已接受的答案,但它是基于你的。【参考方案2】:感谢 blackSphere,我能够找到一些文化和 InvariantCulture 之间的一些差异,如下面的代码所示:
void Demonstration_For_LL()
int foundPos;
foundPos = "ll".IndexOf("l", StringComparison.InvariantCulture);
Assert.AreEqual(0, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("sq", false);
foundPos = "ll".IndexOf("l", StringComparison.CurrentCulture);
Assert.AreEqual(-1, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("sq-AL", false);
foundPos = "ll".IndexOf("l", StringComparison.CurrentCulture);
Assert.AreEqual(-1, foundPos);
void Demonstration_For_CH()
int foundPos;
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(0, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("cs", false);
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(-1, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("cs-CZ", false);
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(-1, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("sk", false);
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(-1, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("sk-SK", false);
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(-1, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("vi", false);
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(-1, foundPos);
Thread.CurrentThread.CurrentCulture = new CultureInfo("vi-VN", false);
foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);
Assert.AreEqual(-1, foundPos);
不幸的是,string.Compare 方法似乎没有显示这些差异。无论如何,我的测试方法现在看起来是这样的:
class Example
public static void Main()
var comparisonTypePerformed =
GetComparisonTypePerformed(
new TestedMethod(string.IndexOf));
Console.WriteLine("Comparison type performed was: " + comparisonTypePerformed);
public static StringComparison GetComparisonTypePerformed(TestedMethod testedMethod)
StringComparison comparisonTypePerformed;
var prevCulture = Thread.CurrentThread.CurrentCulture;
try
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);
// Check if method performs an Ordinal search
int result = testedMethod("œ", "oe", 0, 1, comparisonType);
if (result == StringHelper.NPOS)
// Check if method performs a case-sensitive search
result = testedMethod("a", "A", 0, 1, comparisonType);
if (result == StringHelper.NPOS)
comparisonTypePerformed = StringComparison.Ordinal;
else
comparisonTypePerformed = StringComparison.OrdinalIgnoreCase;
else
Thread.CurrentThread.CurrentCulture = new CultureInfo("sq-AL", false);
// Check if method uses CurrentCulture or InvariantCulture
result = testedMethod("ll", new string[] "l" , 0, 2, comparisonType);
if (result == StringHelper.NPOS)
// Check if method performs a case-sensitive search
result = testedMethod("a", new string[] "A" , 0, 1, comparisonType);
if (result == StringHelper.NPOS)
comparisonTypePerformed = StringComparison.CurrentCulture;
else
comparisonTypePerformed = StringComparison.CurrentCultureIgnoreCase;
else
// Check if method performs a case-sensitive search
result = testedMethod("a", new string[] "A" , 0, 1, comparisonType);
if (result == StringHelper.NPOS)
comparisonTypePerformed = StringComparison.InvariantCulture;
else
comparisonTypePerformed = StringComparison.InvariantCultureIgnoreCase;
finally
Thread.CurrentThread.CurrentCulture = prevCulture;
return comparisonTypePerformed;
delegate int TestedMethod(string source, string value, int startIndex, int count, StringComparison comparisonType);
【讨论】:
【参考方案3】:尝试以 fr-FR 作为您当前的文化的 cote 和 côte。
或使用this MSDN resource 查找其他示例。
我环顾四周,找不到 InvariantCulture 通过字符串比较(仅排序顺序和解析/序列化)与其他文化不同的情况。
我不明白这条评论 - 排序顺序肯定使用 StringComparison。
【讨论】:
é 和 ô 的排序因文化而异,但似乎不会影响平等测试,这正是我所需要的。我更新了问题以尝试更清楚。谢谢 @drifter - 您是否查看过 String.IndexOf 文档中的示例:msdn.microsoft.com/en-us/library/ms224425.aspx。它将字符串与 \u00c5 和 \u0061\u030a 进行比较。也许会给你你想要的。 该示例对 CurrentCulture 和 InvariantCulture 的结果相同。我在其他文化中尝试过它的变体,但没有运气。以上是关于C#:区分 CurrentCulture 和 InvariantCulture 的单元测试的主要内容,如果未能解决你的问题,请参考以下文章
c#实现自然排序效果,按1,2,11而不是1,11,12,区分字母文字和数字
WPF XAML 绑定和 CurrentCulture 显示
.NET 中 CultureInfo 的 CurrentCulture 和 CurrentUICulture 属性有啥区别?