Globally set String.Compare/ CompareInfo.Compare to Ordinal
Asked Answered
W

2

5

I'm searching for a strategy with which I can set the default sortorder of String.CompareTo to bytewise - ordinal. I need to do this without having to specify the sortorder in the call to the method.

I have tried out several strategies without satisfactory results. I got as far as this:

CultureAndRegionInfoBuilder crib = 
            new CultureAndRegionInfoBuilder("foo", CultureAndRegionModifiers.Neutral);

        CompareInfo compareInfo = new CustomCompareInfo();
        crib.Register();

In this CustomCompareInfo I try to override the default CompareInfo class, but unfortunately this does not compile:

The type 'System.Globalization.CompareInfo' has no constructors defined

I'm stuck here. Got the feeling that a custom implementation of CompareInfo is the solution to my problem.

Got any ideas on this?

Edit: context of my question:

This project I'm working on is quite unusual - a huge codebase has been converted from an other programming language to .NET. In this programming language the string comparison defaults to ordinal and this difference with .NET is causing bugs in the converted codebase, so I figured it would be the most elegant solution if we'd be able to configure .NET to the same default behavior.

Of course it is possible to reconvert the code using a comparison-specifier. Or, we could introduce an extension method which performs a ordinal (binary) comparison. Et cetera..

However, as far as I am concerned, from an architectural viewpoint, these solutions are less elegant. This is the reason why I am searching for a solution with which I can set this ordinal comparison globally on the framework.

Thanks in advance!

Woke answered 21/6, 2012 at 12:40 Comment(4)
Eh, why? The framework gives you a means (indeed, several means) to define how a comparison should be done, and a means to access data about a locale including its collation rules. Why do you need to use the latter to do (much easier) the job of the former?Kuibyshev
Not really the answer to the question, but you could 1) define an extension method, MyCompareTo that would do want you want and easily search and replace it massively in the source, or 2) post process the assembly using a tool such as Cecil replacing the call by what you want.Ewan
I'll explain. This project I'm working on is quite unusual - a huge codebase has been converted from an other programming language to .NET. In this programming language the string comparison defaults to ordinal (this difference is causing bugs in our software in .NET), so I figured it would be the most elegant solution if we'd be able to configure .NET to the same default behavior. Of course it is possible to reconvert the code using a comparison-specifier. Or, we could introduce an extension method which performs a ordinal (binary) comparison. Et cetera..Woke
As far as I am concerned, from an architectural viewpoint, these solutions are less elegant.Woke
E
4

Sorry, you can't make this work. The CompareInfo class does have a constructor. But it is internal and takes a CultureInfo as an argument. The actual implementation involves private members of CultureInfo that reflect sorting tables built into mscorlib. They are not extensible.

This does actually work in VB.NET, presumably the reason you are pursuing this. It has an Option Compare statement that lets you select binary comparison. This is however not implemented with CultureInfo, it is done by the compiler. Which recognizes a string comparison and replaces it with a custom vb.net string comparison method that is aware of the selected Option Compare. It's name is Microsoft.VisualBasic.CompilerServices.Operators.CompareString()

You cannot coax the C# compiler into the same behavior. You'd have to painstakingly replace comparison expressions in converted vb.net code. A horrible job of course and very prone to mistakes. If the conversion was done by a converter program then you might be better off with a good decompiler, it won't hide the CompareString() calls.

Empoverish answered 27/6, 2012 at 12:53 Comment(5)
Thanks you, Hans. See my comments for context. I wanted to be absolutely sure.Woke
What am I supposed to see in the comments? Looks like I guessed right at the language conversion. Don't hide details like that in your question, it stops you from getting good answers. You are not the first to run into this problem. Talk to the language converter vendor, I'm sure there are options available. It's an hour of work for them, weeks of chasing bugs for you.Empoverish
You are absolutely right Hans, except that we are the language converter vendor ;-) As you might have guessed, by debugging we are able to track incorrect translations and fix our conversion grammar. This is one of the issues we have found. I've edited my question.Woke
Well, in that case making it a global compare option is a particularly bad idea, you'll break any code that will be added to the project after the conversion. Just give the customer an option to select between a plain and a custom string comparison.Empoverish
You are right. If we "hack" .NET to mimic the behavior of the converted language, this hack will confuse .NET developers who add new code to the project. A decision has been made - we will add CompareInfo.Ordinal to all the calls to CompareTo. Not an elegant solution, but at least it is very clear what is happening. Thanks for your Help Hans, the bounty is yours.Woke
L
1

There appears to be no means of setting the default comparison mode (here, to ordinal).

If what you want is always-consistent comparison results, you can set, for each thread you create in your app, the culture to 'invariant' (cultureInfo with empty string as parameter) Thread.CurrentThread.CurrentCulture = new CultureInfo(""); If you want to perform ordinal comparisons for performance, I really think that nothing can be done globally - you will need to pass this option explicitly each time you perform a string comparison.

Can you tell us what you need exactly?

Latif answered 27/6, 2012 at 13:3 Comment(1)
Thank you, see my comments for more context.Woke

© 2022 - 2024 — McMap. All rights reserved.