Click here to Skip to main content
13,866,342 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


53 bookmarked
Posted 17 Jan 2008
Licenced CPOL

Implementing the .NET IComparer interface to get a more natural sort order

, 4 Jul 2008
Rate this:
Please Sign up or sign in to vote.
The IComparer available in .NET lets you sort numbers or strings. This little class available in both C# and VB shows how to implement an IComparer which will work with mixed characters and numbers.



Did you notice how Explorer in XP is intelligent enough to sort the files in a natural order?

If you have 10 files on your hard disk, they will show in this order:







However, if you try in under DOS, they will appear this way:



The reason for that is that DOS uses a simple alphabetical search.

The aim of this article is to show how I think Explorer does this better than DOS and provide to the CodeProject readers a class to reproduce this in their .NET programs.


The .NET framework uses the IComparer interface a lot. This interface is very simple to implement; it contains a single member:

Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer
int IComparer.Compare(object x, object y)

The function you must provide returns an integer which must be:

  • less than zero when x is less than y
  • zero when x equals y
  • more than zero when x is greater than y

Comparing a null reference (Nothing in Visual Basic) with any reference type is allowed, and does not generate an exception. A null reference is considered to be less than any reference that is not null.

Using the code

The class NaturalComparer can be used anywhere the .NET framework requires an IComparer. That is about every operation which involves sorting data. The most common is probably Array.Sort.

In the demo program, for example, I use:

Array.Sort(lines, New NaturalComparer())

This will sort the lines using the natural order I have briefly described above.

How does this work

This NaturalComparer class uses a couple of StringParser classes to compare each item.

The StringParser is a pretty straightforward character parser. It eats the characters of the string, and returns through its member NextToken a series of tokens. Each token is either numerical or string.

public void NextToken()
    if (mCurChar == '\0')
      mTokenType = NaturalComparer.TokenType.Nothing;
      mStringValue = null;
    else if (char.IsDigit(mCurChar))
      mTokenType = NaturalComparer.TokenType.Numerical;
    else if (char.IsLetter(mCurChar))
      mTokenType = NaturalComparer.TokenType.String;
      // This can also optionally return
      // numericals in case of Roman Numerals
      // Ignore this character and loop some more 
  } while (true);

The StringParser ignores the punctuations and spaces.

The NaturalComparer has very little to do. It will get the first token from each string and compares their numerical values if both are numerical, if not compares the string values.

int System.Collections.Generic.IComparer<string>.Compare(string string1, 
                                                 string string2)
  int result;
    if (mParser1.TokenType == TokenType.Numerical & 
                 mParser2.TokenType == TokenType.Numerical)
      // both string1 and string2 are numerical 
      result = decimal.Compare(mParser1.NumericalValue, mParser2.NumericalValue);
      result = string.Compare(mParser1.StringValue, mParser2.StringValue);
    if (result != 0) return result;
  } while (!(mParser1.TokenType == TokenType.Nothing & 
             mParser2.TokenType == TokenType.Nothing));  
  return 0; //identical 

Points of interest

As an option, you can ask the NaturalComparer to detect and parse Roman numerals.

New NaturalComparer(NaturalComparerOptions.RomanNumbers)

The problem is that sometimes the comparer could mix a valid English name for a Roman number. This is okay if the other side of the comparison is a string, but it can mess your sort order if the other side is a number or another false Roman numeral positive.

So, use this option if you believe the likelihood of having Roman numerals is worth messing the order.


  • 2008 Jan 17: First release.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Pascal Ganaye
Software Developer (Senior)
France France
I am a French programmer.
These days I spend most of my time with the .NET framework, JavaScript and html.

You may also be interested in...


Comments and Discussions

QuestionBound Listbox Sort Pin
Member 1158819110-Aug-16 1:50
memberMember 1158819110-Aug-16 1:50 
Praisevery nice Pin
Member 1139005617-May-16 17:07
memberMember 1139005617-May-16 17:07 
GeneralRe: very nice Pin
Pascal Ganaye19-May-16 8:06
memberPascal Ganaye19-May-16 8:06 
QuestionHow do you implement the NaturalComparer to sort a Class Array ? Pin
Member 30077533-Jul-13 0:04
memberMember 30077533-Jul-13 0:04 
QuestionSorting a Class Array Pin
Member 300775328-Jun-13 1:23
memberMember 300775328-Jun-13 1:23 
AnswerFinal C# version? Pin
Jack Diamond7-May-12 23:39
memberJack Diamond7-May-12 23:39 
GeneralRe: Final C# version? Pin
Jack Diamond8-May-12 0:05
memberJack Diamond8-May-12 0:05 
GeneralBug Pin
chemical_e782-Aug-10 1:14
memberchemical_e782-Aug-10 1:14 
GeneralRe: Bug Pin
Pascal Ganaye2-Aug-10 13:07
memberPascal Ganaye2-Aug-10 13:07 
GeneralThanks Pin
Pieter Muller3-May-10 5:28
memberPieter Muller3-May-10 5:28 
GeneralThis is great! But..... Pin
nfiskeo18-Dec-08 4:42
membernfiskeo18-Dec-08 4:42 
GeneralThanks Pin
Kahiko8-Oct-08 8:34
memberKahiko8-Oct-08 8:34 
GeneralEven more natural PinPopular
Seth Morris22-Jan-08 20:27
memberSeth Morris22-Jan-08 20:27 
GeneralRe: Even more natural Pin
Pascal Ganaye4-Jul-08 3:01
memberPascal Ganaye4-Jul-08 3:01 
GeneralRe: Even more natural Pin
supercat94-Jul-08 9:59
membersupercat94-Jul-08 9:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190214.1 | Last Updated 4 Jul 2008
Article Copyright 2008 by Pascal Ganaye
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid