1.4. Sort Results in a Culture-Sensitive Manner

Problem

You want to ensure that when you sort in a query, the sort order is for an applicationspecific culture that may not be the same as the current thread's current culture.

Solution

Use the overload of the OrderBy query operator, which accepts a custom comparer in order to specify the culture in which to perform comparisons:

	// Create CultureInfo for Danish in Denmark.
	CultureInfo danish = new CultureInfo("da-DK");

	CultureStringComparer comparer = new CultureStringComparer(danish,CompareOptions.
	None);
	var query = names.OrderBy(n => n, comparer);

Discussion

Handling localization issues such as sorting for a specific culture is a relatively trivial task in .NET if the current culture of the current thread is the culture you want to use. The framework classes that assist in handling culture issues in C# are accessed by including the System.Globalization namespace. This namespace would be included in order to make the code in the solution run. One example of not using the thread current culture would be in an application that needs to display a sorted list of words in Danish on a version of Windows XP that is set for U.S. English. The current thread in the application may have a CultureInfo for "en-US" and, by default, the sort order for OrderBy will use the current culture sort settings. To specify that this list should sort according to Danish rules, a bit of work is necessary in the form of a custom comparer:

	CultureStringComparer comparer = new CultureStringComparer(danish,CompareOptions.
	None);

The comparer variable is an instance of a custom comparer class CultureStringComparer defined as implementing the IComparer<T> interface specialized for strings. This class is used to provide the culture settings for the sort order:

	public class CultureStringComparer : IComparer<string>
	{
	    private CultureStringComparer() 
	    {
	    }

	    public CultureStringComparer(CultureInfo cultureInfo, CompareOptions options) 
	    {
	        if (cultureInfo == null) 
	            throw new ArgumentNullException("cultureInfo");

	        CurrentCultureInfo = cultureInfo; 
	        Options = options; 
	    }

	    public int Compare(string x, string y) 
	    {
	        return CurrentCultureInfo.CompareInfo.Compare(x, y, Options); 
	    }

	    public CultureInfo CurrentCultureInfo { get; set; }

	    public CompareOptions Options { get; set; }
	}

To demonstrate how this could be used, first we compile a list of words to order by. Since the Danish language treats the character "Æ" as an individual letter, sorting it after "Z" in the alphabet, and the English language treats the character "Æ" as a special symbol, sorting it before the letter "A" in the alphabet, this will demonstrate the sort difference:

	string[] names = { "Jello", "Apple", "Bar", "Æble", "Forsooth", "Orange", "Zanzibar"
	};

Now, we can set up the CultureInfos for both Danish and U.S. English and call OrderBy with the comparer specific to each culture. This query is not using the query expression syntax, but rather uses the functional style of IEnumerable<string>.OrderBy():

	// Create CultureInfo for Danish in Denmark.
	CultureInfo danish = new CultureInfo("da-DK");
	// Create CultureInfo for English in the U.S.
	CultureInfo american = new CultureInfo("en-US");

	CultureStringComparer comparer = new CultureStringComparer(danish, CompareOptions.
	None);
	var query = names.OrderBy(n => n, comparer);
	Console.WriteLine("Ordered by specific culture : " + comparer.CurrentCultur	eInfo.
	Name);
	foreach (string name in query)
	{
	    Console.WriteLine(name);
	}
	comparer.CurrentCultureInfo = american;
	query = names.OrderBy(n => n, comparer);
	Console.WriteLine("Ordered by specific culture : " + comparer.CurrentCultureInfo.
	Name);
	foreach (string name in query)
	{
	    Console.WriteLine(name);
	}

The output results below show that the word Æble is last in the Danish list and first in the U.S. English list:

	Ordered by specific culture : da-DK
	Apple
	Bar
	Forsooth
	Jello
	Orange
	Zanzibar
	Æble
	Ordered by specific culture : en-US
	Æble
	Apple
	Bar
	Forsooth
	Jello
	Orange
	Zanzibar

See Also

The "OrderBy," "CultureInfo," and "IComparer<T>" topics in the MSDN documentation.

Get C# 3.0 Cookbook, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.