C# EndsWith 有时会给出错误的结果

C# EndsWith sometimes gives false results

"Cs".EndsWith("s") 和"cs".EndsWith("s") 给我“假”。

我整理了一个简单的控制台应用程序来展示问题:

string[] strings = { "s", "As", "Bs", "Cs", "Ds", "Es", "as", "bs", "cs", "ds", "es", "AAs", "ABs", "ACs", "ADs", "AEs" };
foreach (string str in strings)
  Console.WriteLine(str + " ends with 's': " + str.EndsWith("s"));
Console.ReadKey();

结果是这样的:

s ends with 's': True
As ends with 's': True
Bs ends with 's': True
Cs ends with 's': False
Ds ends with 's': True
Es ends with 's': True
as ends with 's': True
bs ends with 's': True
cs ends with 's': False
ds ends with 's': True
es ends with 's': True
AAs ends with 's': True
ABs ends with 's': True
ACs ends with 's': False
ADs ends with 's': True
AEs ends with 's': True

我试过更改目标框架:(VS2013)

也尝试使用 .NET 6.0 的 VS2022 预览版(在两台不同的计算机上),但产生了同样的问题。

在 dotnetfiddle (.NET 4.7.2) 中运行良好...:-O

你能帮我看看我应该在哪里寻找解决方案吗? (设置、安装的软件等)

提前致谢。

正如 Lasse V. Karlsen 所说,只有当 CultureInfo 设置为匈牙利语时才会出现此问题。要为您当前的程序解决这个问题,一个解决方案是将其设置为任何其他文化,例如 en-US.

我在这里就是这么做的:

using System;
using System.Globalization;
using System.Threading;
                    
public class Program
{
    public static void Main()
    {
        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);
        
        string[] strings = { "s", "As", "Bs", "Cs", "Ds", "Es", "as", "bs", "cs", "ds", "es", "AAs", "ABs", "ACs", "ADs", "AEs" };
        foreach (string str in strings)
         Console.WriteLine(str + " ends with 's': " + str.EndsWith("s"));
        Console.ReadKey();
    }
}

在此处运行:https://dotnetfiddle.net/PLEt8x

参考资料:here

一般情况下,最简单的方法是告诉字符串比较器它应该使用序号比较,如下所示:

str.EndsWith("s", StringComparison.Ordinal)

正如评论中的人已经解释的那样,大多数字符串函数都适用于当前的文化,而且这似乎是匈牙利语,这就是为什么你会得到这些结果。

另一个好处是,序号比较是迄今为止最快的。

正如其他人指出的那样,问题与匈牙利语中的组合字母有关。 https://en.wikipedia.org/wiki/Hungarian_alphabet

使用“StringComparison.Ordinal”参数解决了问题。 https://docs.microsoft.com/en-us/dotnet/api/system.string.endswith?view=net-5.0#System_String_EndsWith_System_String_System_StringComparison_

我制作了另一个小程序来测试其中的一些情况:

'''

var list = new List<KeyValuePair<string, string>>()
{
    new KeyValuePair<string,string>("cs", "s"),
    new KeyValuePair<string,string>("dz", "z"),
    new KeyValuePair<string,string>("dzs", "s"),
    new KeyValuePair<string,string>("gy", "y"),
    new KeyValuePair<string,string>("ly", "y"),
    new KeyValuePair<string,string>("ny", "y"),
    new KeyValuePair<string,string>("sz", "z"),
    new KeyValuePair<string,string>("ssz", "z"),
    new KeyValuePair<string,string>("ty", "y"),
    new KeyValuePair<string,string>("zs", "s"),
    new KeyValuePair<string,string>("Cs", "s"),
    new KeyValuePair<string,string>("CS", "S"),
    new KeyValuePair<string,string>("cS", "S"),
    new KeyValuePair<string,string>("Dzs", "s"),
    new KeyValuePair<string,string>("Dzs", "zs"),
    new KeyValuePair<string,string>("Ty", "y"),
    new KeyValuePair<string,string>("Ssz", "z"),
    new KeyValuePair<string,string>("Ssz", "sz"),
};

Console.WriteLine("CultureInfo.CurrentCulture: " + CultureInfo.CurrentCulture);

foreach(var pair in list)
{
    string sLetter = pair.Key;
    string sEnd = pair.Value;
    Console.WriteLine(sLetter + " ends with '" + sEnd + "': " + sLetter.EndsWith(sEnd) + "/" + sLetter.EndsWith(sEnd, StringComparison.Ordinal));
}

'''

结果如下: '''

CultureInfo.CurrentCulture: hu-HU
cs ends with 's': False/True
dz ends with 'z': False/True
dzs ends with 's': False/True
gy ends with 'y': False/True
ly ends with 'y': False/True
ny ends with 'y': False/True
sz ends with 'z': False/True
ssz ends with 'z': False/True
ty ends with 'y': False/True
zs ends with 's': False/True
Cs ends with 's': False/True
CS ends with 'S': False/True
cS ends with 'S': True/True
Dzs ends with 's': False/True
Dzs ends with 'zs': False/True
Ty ends with 'y': False/True
Ssz ends with 'z': False/True
Ssz ends with 'sz': True/True

'''

感谢大家的帮助!