I want to use List.BinarySearch()
with a custom item type. The custom type does not implement IComparable<T>
; instead I have several static Comparison<T>
functions that I call because at various points I want to sort the list on different criteria. Plus I think it adds clarity since the way you are sorting can be described by the function name. Now I want to do a binary search on the list. I wanted to use one of my comparison functions, only to find that List.BinarySearch()
doesn't have an overload that accepts Comparison<T>
, only IComparer<T>
. I try to avoid IComparer<T>
because it seems silly to me to have a separate class just for comparing objects. Why doesn't List.BinarySearch()
have overloads that take Comparison<T>
in addition to IComparer<T>
? And is there any way to use my existing Comparison<T>
functions in List.BinarySearch()
?
Asked
Active
Viewed 3,220 times
6

Craig W
- 4,390
- 5
- 33
- 51
-
where is the code that you are using to do the search a foreach or for loop..?? – MethodMan Dec 06 '11 at 19:48
-
1Create a comparer that delegates to your comparison. Good to go. – Anthony Pegram Dec 06 '11 at 19:48
-
Can anybody answer my first question: why doesn't List.BinarySearch() have overloads that take Comparison
in addition to just IComparer – Craig W Dec 06 '11 at 19:55? Just out of curiosity... -
1It's an omission, we should report the bug to Microsoft. – Colonel Panic Jul 30 '15 at 11:05
-
1Please vote for the bug report at https://github.com/dotnet/coreclr/issues/2188 – Colonel Panic Feb 16 '16 at 12:03
3 Answers
11
It's very easy to create an IComparer<T>
from a Comparison<T>
- here's a (slightly amended) class from MiscUtil which you're welcome to use:
/// <summary>
/// Utility to build an IComparer implementation from a Comparison delegate,
/// and a static method to do the reverse.
/// </summary>
public class ComparisonComparer<T> : IComparer<T>
{
private readonly Comparison<T> comparison;
public ComparisonComparer(Comparison<T> comparison)
{
if (comparison == null)
{
throw new ArgumentNullException("comparison");
}
this.comparison = comparison;
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}
You could also add an extension method to List<T>
to do this for you:
public static int BinarySearch<T>(this List<T> list, Comparison<T> comparison)
{
return list.BinarySearch(new ComparisonComparer(comparison));
}

Jon Skeet
- 1,421,763
- 867
- 9,128
- 9,194
-
1I guess this is the best solution, although I'm not overly fond of it. I am still very curious about why the overloads don't exist to use Comparison
directly. – Craig W Dec 07 '11 at 00:15 -
1@Craig: As ever, there's a cost to introducing anything. I suspect that the BCL maintainers feel it doesn't quite make the bar of utility against cost. – Jon Skeet Dec 07 '11 at 05:08
-
@JonSkeet: I don't see why that would be, since there's an equivalent overload for `.Sort()` that does use `Comparison
`. I think they just overlooked it. – BlueRaja - Danny Pflughoeft Jul 25 '13 at 21:25 -
@BlueRaja-DannyPflughoeft: It may well not have been the same person making the decision for both methods, of course. – Jon Skeet Jul 25 '13 at 21:27
1
Create wrapper for Comparison
such as this one:
public class ComparisonWrapper<T> : IComparer<T>
{
private Comparison<T> comparison;
public ComparisonWrapper(Comparison<T> comparison)
{
this.comparison = comparison;
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}

MagnatLU
- 5,967
- 1
- 22
- 17
0
Here's an extension on Jon's answer that takes a lambda expression.
public static class ListExtensions
{
public static int BinarySearch<T>(this List<T> list, T item, Func<T, T, int> compare)
{
return list.BinarySearch(item, new ComparisonComparer<T>(compare));
}
}
public class ComparisonComparer<T> : IComparer<T>
{
private readonly Comparison<T> comparison;
public ComparisonComparer(Func<T, T, int> compare)
{
if (compare == null)
{
throw new ArgumentNullException("comparison");
}
comparison = new Comparison<T>(compare);
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}

Daniel Imms
- 47,944
- 19
- 150
- 166