We all had the issue with an OrderBy on a collection of String, having that kind of result:

Test1

Test10

Test2

Test20

Test3

Instead of:

Test1

Test2

Test3

Test10

Test20

Here is the solution:

public class NaturalComparer : Comparer<string>
{
    public override int Compare(string x, string y)
    {
        if (x == y) return 0;

        string[] x1, y1;
        x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)");
        y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)");

        for (int i = 0; i < x1.Length && i < y1.Length; i++)
            if (x1[i] != y1[i]) return PartCompare(x1[i], y1[i]);

        if (y1.Length > x1.Length) return 1;
        else if (x1.Length > y1.Length) return -1;
        else return 0;
    }

    private static int PartCompare(string left, string right)
    {
        int x, y;

        if (int.TryParse(left, out x) && int.TryParse(right, out y))
            return x.CompareTo(y);

        return left.CompareTo(right);
    }
}

public class ReverseNaturalComparer : NaturalComparer
{
    public override int Compare(string x, string y)
    {
        return base.Compare(y, x);
    }
}

And this is how to use it:

[TestClass]
public class NaturalComparer_Test
{
    public List<string> _unsortedCollection
    {
        get
        {
            var stringCollection = new List<string>();

            stringCollection.Add("Test10");
            stringCollection.Add("Test3");
            stringCollection.Add("Test1");
            stringCollection.Add("Test20");
            stringCollection.Add("Test2");

            return stringCollection;
        }
        private set { }
    }

    [TestMethod]
    public void NaturalSort_Test()
    {
        var sortedCollection = _unsortedCollection
            .OrderBy(x => x, new NaturalComparer())
            .ToList();

        Assert.IsNotNull(sortedCollection);
        Assert.IsTrue(sortedCollection.Last() == "Test20");
    }

    [TestMethod]
    public void ReversNaturalSort_Test()
    {
        var sortedCollection = _unsortedCollection
            .OrderBy(x => x, new ReverseNaturalComparer())
            .ToList();

        Assert.IsNotNull(sortedCollection);
        Assert.IsTrue(sortedCollection.Last() == "Test1");
    }
}

Happy coding!  😉