Capita spesso di dover ordinare alfabeticamente una lista di stringhe. Quando si devono ordinare stringhe che contengono numeri, i metodi standard (come quello utilizzato, ad esempio, impostando la proprietà Sorted di un controllo ListBox su True) non sempre producono il risultato voluto.
In casi del genere, infatti, una sequenza come la sequente: A1, A5, A20, A2, A6, A30.
Viene ordinata così: A1, A2, A20, A30, A5, A6.
Mentre è più logico aspettarsi che l'ordinamento produca: A1, A2, A5, A6, A20, A30 (è il cosiddetto ordinamento logico). Questo avviene perché l'ordinamento controlla il valore di ogni singolo carattere, ma nel caso di numeri essi andrebbero controllati "per intero".
Windows, in effetti, utilizza quest'ultimo sistema per ordinare i file nelle finestre di Explorer. L'ordinamento è effettuato richiamando la funzione StrCmpLogicalW. Grazie al Platform Invoke, è possibile utilizzare questo metodo per creare un oggetto .NET in grado di ordinare le stringhe in modo logico:
public class StringLogicalComparer : IComparer
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int StrCmpLogicalW(string strA, string strB);
public int Compare(object x, object y)
{
string strA = x as string;
if(strA != null)
{
string strB = y as string;
if (strB != null)
return StrCmpLogicalW(strA, strB);
}
return Comparer.Default.Compare(x, y);
}
}
Di seguito un semplice esempio di utilizzo:
string[] names = { "A1", "A5", "A20", "A2", "A6", "A30"};
Array.Sort(names); //Usa l'ordinamento standard.
Array.Sort(names, new StringLogicalComparer()); //Usa l'ordinamento logico.
La funzione StrCmpLogicalW si comporta in modo leggermente diverso sotto Windows XP/2003 e sotto Windows Vista quando si devono ordinare nome di file. Per maggiori informazioni, consiglio di leggere Logical StrCmpLogicalW changes in Vista di Michael S. Kaplan.