There is no built-in comparison method to do what you want, but I assume this is not the "long branch" that you are talking about.
What's annoying is that you need to create your own comparison class in order to pass what should be a simple comparison function.
Well, there is a way to mitigate this. You can write a couple of helper classes that let you use OrderBy () just by passing in the method name. If you write these classes, they will work for ALL of your OrderBy () statements.
Here is a sample code. Helper classes are called EnumerableExt and ComparisonDelegator. They work together so you can pass the OrderBy () method.
The code below is clearly much longer than your code, but remember that the EnumerableExt and ComparisonDelegator classes would be in a separate common assembly, so you should not consider them.
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; namespace Demo { public static class Program { private static void Main(string[] args) { var unorderered = new[] { "a", "b", "c", "x", "y", "z" }; var ordered = unorderered.OrderBy(compare); // Just need to specify the compare method! } // Each custom compare method must be written specially, as before: private static int compare(string x, string y) { if (x == y) return 0; else { //---------------------------- //beginning of custom ordering var customPriority = new[] { "y", "x" }; if (customPriority.Any(a => a == x) && customPriority.Any(a => a == y)) //both in custom ordered array { if (Array.IndexOf(customPriority, x) < Array.IndexOf(customPriority, y)) return -1; return 1; } else if (customPriority.Any(a => a == x)) //only one item in custom ordered array (and its x) return -1; else if (customPriority.Any(a => a == y)) //only one item in custom ordered array (and its y) return 1; //--------------------------- //degrade to default ordering else return string.Compare(x, y); } } } // The following classes only need to be written once: public static class EnumerableExt { /// <summary> /// Convenience method on IEnumerable{T} to allow passing of a /// Comparison{T} delegate to the OrderBy method. /// </summary> public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, Comparison<T> comparison) { Contract.Requires(list != null, "list can't be null."); Contract.Requires(comparison != null, "comparer can't be null."); return list.OrderBy(t => t, new ComparisonDelegator<T>(comparison)); } } /// <summary> /// Provides a mechanism for easily converting a Comparison<> delegate (or lambda) to an IComparer<>. /// This can be used for List.BinarySearch(), for example. /// </summary> /// <typeparam name="T">The type of items to be compared.</typeparam> public sealed class ComparisonDelegator<T>: IComparer<T>, IComparer { /// <summary>Create from a Comparison<> delegate.</summary> /// <param name="comparison">A Comparison<> delegate.</param> public ComparisonDelegator(Comparison<T> comparison) { Contract.Requires(comparison != null); this._comparison = comparison; } /// <summary>Implements the IComparer.Compare() method.</summary> public int Compare(T x, T y) { return _comparison(x, y); } /// <summary>Implements the IComparer.Compare() method.</summary> public int Compare(object x, object y) { return _comparison((T)x, (T)y); } /// <summary>Used to store the Comparison delegate.</summary> private readonly Comparison<T> _comparison; } }
Then you can also write the inline comparison method as follows (but I would not recommend this for such a complicated comparison method, this is for illustration purposes only):
private static void Main(string[] args) { var unorderered = new[] { "a", "b", "c", "x", "y", "z" }; var ordered = unorderered.OrderBy((x, y) => { if (x == y) return 0; else { var customPriority = new[] { "y", "x" }; if (customPriority.Any(a => a == x) && customPriority.Any(a => a == y)) //both in custom ordered array { if (Array.IndexOf(customPriority, x) < Array.IndexOf(customPriority, y)) return -1; return 1; } else if (customPriority.Any(a => a == x)) //only one item in custom ordered array (and its x) return -1; else if (customPriority.Any(a => a == y)) //only one item in custom ordered array (and its y) return 1; else return string.Compare(x, y); } }); }