Implementing multiple custom sorts The following code works, but I'm sure there's a cleaner way to implement it and I'd appreciate any guidance on how to go about that.

I have a class Result which I want to sort sometimes by score (which is just an int) and sometimes by parts which are strings whose first char is a digit in [1,7] and whose second char is one of C, D, H, S, N (which are in alphabetical order except that the N needs to come last).

public class Result : IEquatable&lt;Result&gt;, IComparable&lt;Result&gt;
{
    private int score;// Unique NS value for all par contracts.
    private string pars;// All possible pars on this deal.

  // Default comparer for Result type.
    public int CompareTo(Result compareResult)
    {
        // A null value means that this object is greater.
        if (compareResult == null)
            return 1;

        else
            return this.Score.CompareTo(compareResult.Score);
    }
    public override int GetHashCode()
    {
        return score;
    }

    public bool Equals(Result other)
    {
        if (other == null) return false;
        return (this.Score.Equals(other.Score));
    }

    public override string ToString()
    {
        return "Score: " + Score + "   Par: " + Pars;
    }
};




public class InitArray
{
    public static readonly char[] bridgeChar = new char[Constants.CHAR_MAX];

    static InitArray()
    {
        for (int i = 0; i &lt; bridgeChar.Length; i++)
        {
            bridgeChar[i] = Char.ToUpper((char)i);
        }
        //Only concerned with ordering C, D, H, S, N=NT.
        bridgeChar['N'] = bridgeChar['Z'];
    }
};

static void Main(string[] args)
{

    Result result = new Result();

    // Create a list of results.
    List&lt;Result&gt; results = new List&lt;Result&gt;();

    // Add results to the list.
    results.Add(new Result() { Score = 110, Pars = "3C" });
    results.Add(new Result() { Score = -200, Pars = "4Hx" });
    results.Add(new Result() { Score = -100, Pars = "3Hx" });
    results.Add(new Result() { Score = -100, Pars = "3Sx" });
    results.Add(new Result() { Score = 400, Pars = "3N" });

    // Sort on the list using the default comparer.

    results.Sort();

    // Sort calling the Sort(Comparison(T) overload using 
    // an anonymous method.
    results.Sort(delegate (Result x, Result y)
    {
        if (x.Score == 0 &amp;&amp; y.Score == 0) return 0;
        else if (x.Score == 0) return -1;
        else if (y.Score == 0) return 1;
        else return x.Score.CompareTo(y.Score);
    });

    Console.WriteLine("\nAfter sort by score:");
    foreach (Result aResult in results)
    {
        Console.WriteLine(aResult);
    }

    // Sort on pars using an anonymous method.
    results.Sort(delegate (Result x, Result y)
    {
        if ((x == null) &amp;&amp; (y == null)) return 0;
        else if (x == null) return -1;
        else if (y == null) return 1;
        else
        {// Compare the two strings.
            if (x.Pars[0].CompareTo(y.Pars[0]) == 0)
            {
                // If the strings start with the same character, sort them by Denomination.
                return InitArray.bridgeChar[y.Pars[1]].CompareTo(InitArray.bridgeChar[x.Pars[1]]);
            }
            else
            { // sort them with ordinary string comparison.
                return x.CompareTo(y);
            }
        }
    });

    results.Reverse(); //Need them in ascending order.

    Console.WriteLine("\nAfter sort by denom:");
    foreach (Result aResult in results)
    {
        Console.WriteLine(aResult);
    }
  }
}


Output is as required:



After sort by score:
Score: -200   Par: 4Hx
Score: -100   Par: 3Hx
Score: -100   Par: 3Sx
Score: 110   Par: 3C
Score: 400   Par: 3N

After sort by denom:
Score: 110   Par: 3C
Score: -100   Par: 3Hx
Score: -100   Par: 3Sx
Score: 400   Par: 3N
Score: -200   Par: 4Hx
Without getting into why you designed your business logic this way (I would've made Pars a separate class or struct, to accommodate the complexity), I guess this is somewhat a decent approach.

By using an IComparer&lt;T&gt;, you can implement whatever logic you need, thus separating the concern of sorting Pars into its own place.

I've used a predefined list of characters (in C#, the simplest list of char is string, but you can use any type that has an IndexOf method) in order to have a single, distinct source of truth for the order of the chars that can be easily modified without breaking anything. I've named it PairOrder for lack of a better name, feel free to name it whatever you like. 

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
  public static void Main()
  {
    var data = new[] {
      new Result { Score = 110, Pars = "3C" },
      new Result { Score = -200, Pars = "4Hx" },
      new Result { Score = -100, Pars = "3Hx" },
      new Result { Score = -100, Pars = "3Sx" },
      new Result { Score = 400, Pars = "3N" }
    };

    var sortedByScore = data.OrderBy(item =&gt; item.Score)
      .ThenBy(item =&gt; item.Pars, new ParsComparer());

    Console.WriteLine("Sorting by Score first");
    foreach (var item in sortedByScore)
    {
      Console.WriteLine(item);
    }

    var sortedByPars = data.OrderBy(item =&gt; item.Pars, new ParsComparer())
      .ThenBy(item =&gt; item.Score);

    Console.WriteLine("\nSorting by Pars first");
    foreach (var item in sortedByPars)
    {
      Console.WriteLine(item);
    }
  }
}

public class Result
{
  public int Score { get; set; }
  public string Pars { get; set; }

  public override string ToString()
  {
    return string.Format("Score: {0}; Pars: {1}", Score, Pars);
  }
}

public class ParsComparer : IComparer&lt;string&gt;
{
  private string ParsOrder = "CDHSN";

  public int Compare(string a, string b)
  {
    var delta = a[0].CompareTo(b[0]);

    if (delta == 0)
    {
      var indexA = ParsOrder.IndexOf(a[1]);
      var indexB = ParsOrder.IndexOf(b[1]);

      delta = indexA.CompareTo(indexB);
    }

    return delta;
  }
}


The output is what you expected:

Sorting by Score first
Score: -200; Pars: 4Hx
Score: -100; Pars: 3Hx
Score: -100; Pars: 3Sx
Score: 110; Pars: 3C
Score: 400; Pars: 3N

Sorting by Pars first
Score: 110; Pars: 3C
Score: -100; Pars: 3Hx
Score: -100; Pars: 3Sx
Score: 400; Pars: 3N
Score: -200; Pars: 4Hx


Disclaimer: it's been a while since I've written any significant C# code. There are probably better ways to write and organize this code.

I also don't make any promises regarding performance. I don't think you'll have any issues, but the IndexOf lookup might introduce a bottleneck, specially if the list of chars gets too big.