C# 排序列表时出现意外行为<;字符串>;

C# 排序列表时出现意外行为<;字符串>;,c#,list,linq,cultureinfo,C#,List,Linq,Cultureinfo,如果我尝试按以下方式对字符串列表排序: List<String> lstStrings = new List<string>(); String s1 = "KÜHLSCHRANK"; String s2 = "KUHLSCHRANK"; int i = s1.CompareTo(s2); // returns 1 int j = s2.CompareTo(s1); // return -1 i = StringComparer.InvariantCultu

如果我尝试按以下方式对字符串列表排序:

List<String> lstStrings = new List<string>();

String s1 = "KÜHLSCHRANK";
String s2 = "KUHLSCHRANK";
int i = s1.CompareTo(s2);   // returns 1
int j = s2.CompareTo(s1);   // return -1 

i = StringComparer.InvariantCulture.Compare(s1, s2); // returns 1
j = StringComparer.InvariantCulture.Compare(s2, s1); // returns -1

lstStrings.Add("KÜHLSCHRANK1");
lstStrings.Add("KUTTER");
lstStrings.Add("KUHLSCHRANK2");
lstStrings.Add("KÜHLSCHRANK3");

var lstStrings1 = lstStrings.OrderBy(y => y).ToList();
var lstStrings2 = lstStrings.OrderBy(y => y, StringComparer.InvariantCulture).ToList();
var lstStrings3 = lstStrings.OrderBy(y => y, StringComparer.CurrentCulture).ToList();
var lstStrings4 = lstStrings.OrderBy(y => y, StringComparer.Ordinal).ToList();
只有我的lstStrings4显示了我预期的结果:

    [0] "KUHLSCHRANK2"  
    [1] "KUTTER"    
    [2] "KÜHLSCHRANK1"
    [3] "KÜHLSCHRANK3"
有人能解释为什么德语的“Ü”在默认情况下像普通的“U”一样有螺纹吗

为什么使用StringComparer.InvariantCulture的OrderBy不关心
StringComparer.InvariantCulture.Compare(s1,s2)
的结果(这意味着列表的顺序与上一个示例中我的lstStrings4相同)

有没有办法改变这种“默认行为”

增加: 如果我将数字附加到字符串,则比较方法的结果会更改:

        String s1 = "KÜHLSCHRANK1";
        String s2 = "KUHLSCHRANK2";
        int i = s1.CompareTo(s2);   // returns -1
        int j = s2.CompareTo(s1);   // return 1 

        i = StringComparer.InvariantCulture.Compare(s1, s2); // returns -1
        j = StringComparer.InvariantCulture.Compare(s2, s1); // returns 1
所以我甚至不明白,为什么我的第一个没有数字的测试每次比较都不返回零

第二次增补: 在SQL Server上:

DECLARE @tableDE TABLE (strName NVARCHAR(MAX) COLLATE German_PhoneBook_CI_AI)

INSERT INTO @tableDE (strName)
SELECT e FROM (VALUES('KUHLSCHRANK1'), ('KÜHLSCHRANK2')) f(e)

SELECT * FROM @tableDE ORDER BY strName
结果是:

KÜHLSCHRANK2
KUHLSCHRANK1
因此: 如果我在LinqToSql中执行一个
OrderBy
,并将结果放入一个列表中,
列表变量上新的
OrderBy
,即使参数相同,也会改变元素的顺序。

我可以回答为什么ordinal会给您“预期”的结果。根据
StringComparer.Ordinal

Ordinal属性返回的StringComparer执行独立于语言的简单字节比较。这在比较以编程方式生成的字符串或比较区分大小写的资源(如密码)时最合适

所以
U
0x55
Ü
0x220
。所以这就把你不同的U分类了。但这有一个问题,假设你添加了单词
KËTTER
(可能不是真正的德语单词,但它是为了演示目的)。您的列表将按如下方式组织:

[0] "KUHLSCHRANK2"
[1] "KUTTER"
[2] "KËTTER"
[3] "KÜHLSCHRANK1"
[4] "KÜHLSCHRANK3"

正如您所看到的,
Ë
位于两个不同的U之间,这是因为
Ë
的unicode为
0x203
,而
55您的初始比较并不十分有用,因为这些字符串从未出现在排序列表中。我建议您尝试比较“KÜHLSCHRANK1”和“KUHLSCHRANK2”。@JonSkeet:添加了请求的exampleRight,因此所有排序部分现在都完全不相关,应该删除。(我怀疑答案是“umlaut仅在平局中相关”或类似内容)这里总结的总体字符串比较(增加了德国文化的比较):。检查结果是否正确。我不同意维基百科的文章。例如,刚刚在SQLServer上测试过。德国电话簿100_CI_AI的排序规则威胁它为单独的字母。嘿,我更新了我的答案,以显示如何像德国电话簿那样排序。我为花这么长时间表示歉意。谢谢你的帮助
[0] "KUHLSCHRANK2"
[1] "KUTTER"
[2] "KËTTER"
[3] "KÜHLSCHRANK1"
[4] "KÜHLSCHRANK3"
[0] "KÜHLSCHRANK1"
[1] "KUHLSCHRANK1"
[2] "KUTTER"
[3] "KUHLSCHRANK2"
[4] "KÜHLSCHRANK2"
[5] "KÜHLSCHRANK3"
[6] "KËTTER"
[0] "KËTTER"
[1] "KUHLSCHRANK1"
[2] "KÜHLSCHRANK1"
[3] "KUHLSCHRANK2"
[4] "KÜHLSCHRANK2"
[5] "KÜHLSCHRANK3"
[6] "KUTTER"
[0] "KËTTER"
[1] "KUHLSCHRANK1"
[2] "KUHLSCHRANK2"
[3] "KUTTER"
[4] "KÜHLSCHRANK1"
[5] "KÜHLSCHRANK2"
[6] "KÜHLSCHRANK3"
[0] "KËTTER"
[1] "KÜHLSCHRANK1"
[2] "KÜHLSCHRANK2"
[3] "KÜHLSCHRANK3"
[4] "KUHLSCHRANK1"
[5] "KUHLSCHRANK2"
[6] "KUTTER"
var germanPhone=new CultureInfo(0x00010407);
StringComparer germanPhoneICComp = StringComparer.Create(germanPhone, true);\\set to false if caps are important to you
var lstStrings7 = lstStrings.OrderBy(y => y, germanPhoneICComp).ToList();