Три варианта:
- Создайте фиктивный Range и поглотите его. Urgh.
- Ручной бинарный поиск только для этого случая. Не так уж плохо.
- Обобщение бинарного поиска для любого IList и TValue, заданного IRangeComparer. Я не в восторге от названия «TRange» здесь - мы не обязательно говорим о диапазонах, но просто находим правильное место, основываясь на сравнении двух разных типов.
Третий вариант: что-то , например:
public interface IRangeComparer<TRange, TValue>
{
/// <summary>
/// Returns 0 if value is in the specified range;
/// less than 0 if value is above the range;
/// greater than 0 if value is below the range.
/// </summary>
int Compare(TRange range, TValue value);
}
/// <summary>
/// See contract for Array.BinarySearch
/// </summary>
public static int BinarySearch<TRange, TValue>(IList<TRange> ranges,
TValue value,
IRangeComparer<TRange, TValue> comparer)
{
int min = 0;
int max = ranges.Count-1;
while (min <= max)
{
int mid = (min + max) / 2;
int comparison = comparer.Compare(ranges[mid], value);
if (comparison == 0)
{
return mid;
}
if (comparison < 0)
{
min = mid+1;
}
else if (comparison > 0)
{
max = mid-1;
}
}
return ~min;
}
Извините, если у меня возникли какие-то ошибки. Я вообще не проверял, но он по крайней мере компилируется:)