6
"strasse".Equals("STRAße",StringComparison.InvariantCultureIgnoreCase)

This returns true. Which is correct. Unfortunately, when I store one of these in postgres, it thinks they are not the same when doing a case insensitive match (for example, with ~*). I've also tested with citext.

So one solution would be to pre-fold the case, thus storing strasse for either of these values, in another column. I could then index and search on that for matches.

I've been looking for how to fold case in C# for a while, and haven't been able to find a solution in C#. Obviously that knowledge is there because it can compare these strings properly, I just can't find where to get it from.

One solution would be to spawn a perl process perl -E "binmode STDOUT, ':utf8'; binmode STDIN, ':utf8'; while (<>) { print fc }", set the C# side of the process to utf8 for those pipes as well, and just send the text through perl to fold the case. But there has to be a better way than that.

Tanktalus
  • 21,664
  • 5
  • 41
  • 68

2 Answers2

0

Looking through the sources I eventually found that most of this implementation is in a set of classes called CompareInfo.

You can find these at github.com/dotnet/runtime

That led me to this page that clues in to the inner workings for the .net culture stuff. .NET globalization and ICU

It seems that dotnet is actually relying completely on native libraries for everything except ordinal operations.

I would assume by this that the .Net Framework is probably using NLS from Win32. For that there is the FoldStringW method that looks promising.

For ICU there is documentation for Case Mappings and I found the u_strFoldCase method.

Tamir Daniely
  • 1,659
  • 1
  • 20
  • 24
0

There is string.Normalize(), which takes a NormalizationForm parameter. Michael Kaplan goes into detail on this. He claims it does a better job than FoldStringW.

It does not, however, normalize the case to upper or lower, it only folds to the canonical form. I would suggest you just apply ToUpper or ToLower afterwards.

Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • The entire original point was to normalise case, although normalising the rest of unicode with combining characters and all that would likely also play a role in matching stuff later. – Tanktalus Dec 31 '20 at 04:14
  • When I said "normalize case" I meant specifically to upper or lower case, rather than folding to canonical forms, which was also part of the question. – Charlieface Dec 31 '20 at 04:27
  • ToUpper / ToLower don't work for case-insensitive matches in all languages, that's part of the problem. – Tanktalus Dec 31 '20 at 14:23
  • Even after `string.Normalize`? – Charlieface Dec 31 '20 at 14:32
  • Did you try it with the above strings? I just pushed it through net core 3.1, and, unsurprisingly, it doesn't do what is required. – Tanktalus Jan 02 '21 at 20:33