C#中的字符串排序问题

我有这样的列表

List items = new List(); items.Add("-"); items.Add("."); items.Add("a-"); items.Add("a."); items.Add("aa"); items.Add("aa"); items.Sort(); string output = string.Empty; foreach (string s in items) { output += s + Environment.NewLine; } MessageBox.Show(output); 

输出回来了

 - . a- aaa aa 

在哪里我期待结果为

 - . a- a. aa aa 

知道为什么“aa”没有出现在“aa”之前,其中“a-”出现在“a”之前。

如果希望字符串排序基于实际字节值而不是当前文化定义的规则,则可以按Ordinal排序:

items.Sort(StringComparer.Ordinal);

这将使结果在所有文化中保持一致(但是它会在“9”之前产生不直观的“14”排序,这可能是也可能不是你想要的)。

我怀疑在最后一种情况下,由于特定于文化的设置(可能是“破折号”而不是第一个字符串中的“减号”),“ – ”会以不同的方式处理。 MSDN警告 :

比较使用当前文化来获取特定于文化的信息,例如套管规则和单个字符的字母顺序。 例如,文化可以指定某些字符组合被视为单个字符,或者以特定方式比较大写和小写字符,或者字符的排序顺序取决于其前面或后面的字符。

另请参阅此MSDN页面 :

.NET Framework使用三种不同的排序方式:单词排序,字符串排序和顺序排序。 单词排序执行文化敏感的字符串比较。 某些非字母数字字符可能会分配特殊权重; 例如,连字符(“ – ”)可能具有非常小的权重,因此“coop”和“co-op”在排序列表中彼此相邻。 字符串排序类似于单词排序,除了没有特殊情况; 因此,所有非字母数字符号都在所有字母数字字符之前。 序数排序根据字符串中每个元素的Unicode值比较字符串。

因此,连字符在默认排序模式下获得特殊处理,以使单词排序更“自然”。

如果您专门打开它,您可以获得“正常”序数排序:

  Console.WriteLine(string.Compare("a.", "a-")); //1 Console.WriteLine(string.Compare("aa", "aa")); //-1 Console.WriteLine(string.Compare("a.", "a-", StringComparison.Ordinal)); //1 Console.WriteLine(string.Compare("aa", "aa", StringComparison.Ordinal)); //1 

要使用序数比较对原始集合进行排序,请使用:

  items.Sort(StringComparer.Ordinal); 

List<>类的Sort方法依赖于.NET Framework的默认string比较器,它实际上是Thread的当前CultureInfo的一个实例。

CultureInfo指定字符的字母顺序,似乎默认的字符使用的顺序与您期望的顺序不同。

排序时,您可以指定一个特定的CultureInfo ,您知道它将符合您的排序要求,样本(德国文化):

 var sortCulture = new CultureInfo("de-DE"); items.Sort(sortCulture); 

更多信息可以在这里找到:
http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
http://msdn.microsoft.com/de-de/library/system.stringcomparer.aspx