2

"Cs".EndsWith("s") and "cs".EndsWith("s") gives me "false".

I put together a simple console application to present the problem:

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();

The result is this:

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

I have tried changing the target framework: (VS2013)

  • all 4.x versions produced this error
  • on .NET 3.5, 3.0, 2.0 worked well.

Also tried with VS2022 Preview (on 2 different computers) with .NET 6.0 but produced the same problems.

In dotnetfiddle (.NET 4.7.2) it works well... :-O

Can you help me where shall I look for the solution? (settings, installed softwares, etc.)

Thanks in advance.

3 Answers3

1

As Lasse V. Karlsen commented, this problem only occurs when the CultureInfo is set to Hungarian. To solve that for your current program, a solution would be to set it to any other culture, like for example en-US.

I do exactly that here:

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();
    }
}

Runs here: https://dotnetfiddle.net/PLEt8x

Documents for reference: here

Costa
  • 1,794
  • 1
  • 12
  • 21
1

In general the easiest way in your case is to tell the string comparer it should use ordinal comparison like so:

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

As people in the comments allready explained, most string-functions work with the current culture, and that appears to be hungarian, thats why you are getting theese results.

Another benefit is, that ordinal comparison is by far the fastest.

CSharpie
  • 9,195
  • 4
  • 44
  • 71
1

As others pointed out the problem is in connection with the combined letters in Hungarian language. https://en.wikipedia.org/wiki/Hungarian_alphabet

Using "StringComparison.Ordinal" parameter solved the problem. https://learn.microsoft.com/en-us/dotnet/api/system.string.endswith?view=net-5.0#System_String_EndsWith_System_String_System_StringComparison_

I made another small program to test some of these cases:

'''

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));
}

'''

Which gives the following result: '''

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

'''

Thanks everyone for the help!