by Michael S. Kaplan, published on 2005/04/13 09:19 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2005/04/13/407823.aspx
I have talked about LOCALE_INVARIANT / CultureInfo.InvariantCulture before, in Comparison confusion: INVARIANT vs. ORDINAL and Where is the locale? "Its Invariant." In where? and talked a little about the if not noble then at least deterministic intent of this odd locale with no real country and no real language. But when I look at how people use it, what I am most often struck by is two different things:
That post I link to for LOCALE_INVARIANT has probably the best description I have ever seen of the purpose of Invariant:
The LOCALE_INVARIANT is a special locale identifier that is locale independent. It is designed for system level functions that require consistent results (for example, sorting in the file system) regardless of the locale that the user has chosen. Typically, an application does not use LOCALE_INVARIANT because it expects the results of an action to depend on the rules governing each individual locale.
LOCALE_INVARIANT is defined as LANG_INVARIANT for the primary language, SUBLANG_NEUTRAL for the sub-language, and SORT_DEFAULT for the sort id.
In fact the only real problem with this summary is that it located in the remarks for the MAKESORTLCID macro, whose only connection to LOCALE_INVARIANT is that like all proper LCIDs you can construct the value with the macro if you did not want to use the predetermined constant. At least they mention how the construction is done (I have seen developers wonder why MAKELLANGID(LANG_INVARIANT, SUBLANG_DEFAULT) causes an error when you try to use it -- I tell them to just the predefined constant and not try to build them all when you do not have to!).
The most common misuse is for people to do a ToLower() operation followed by an invariant comparison to validate filenames, which if you are a regular reader here you will know that it is hard to get less accurate results out of code than this approach. Well, you could write code that reformats the user's hard drive when you run it and that would be worse. But it is in the top five "bad algorithms you can create while soberly writing code." With the bonus of being an extra string allocation.
Yikes!
I have decided that I will from time to time remind people of the difference between ORDINAL and INVARIANT, because neither name is all that intuitive but each of them can be incredibly useful (when used properly/appropriately). As I said in the first article above:
That problem remains to this day, though every single time I speak at a conference or answer a question in a newsgroup or get someone to look at posts like this one, then there is at least one less developer who has this problem. Maybe this time it is you? :-)
I kind of feel a summarized list of DOs and DON'Ts coming on in a future post, and the issues surrounding Invariant and Ordinal comparisons will probably have a prominent place in that list (as will some of those casing issues).
This post brought to you by "ლ" (U+10da, a.k.a. GEORGIAN LETTER LAS)
# Ben on 13 Apr 2005 10:39 PM:
# Michael S. Kaplan on 14 Apr 2005 8:13 AM:
referenced by
2006/05/24 Invariant vs. Ordinal, the third
2005/12/22 New in Windows Vista: OrdinalIgnoreCase for Win32
2005/10/15 If you are using INVARIANT then you are probably MISusing it, #1
2005/06/02 The New String recommendations
2005/04/14 On approaching international programming....