Вы можете либо реализовать IComparable<T>
для своей структуры для сравнения в поле (F), либо вы можете создать IComparer<>
для своей структуры, которая будет сравнивать на основе этого поля и передавать ее в Array.BinarySearch()
.
Так что либо:
// using IComparable<T>
public struct MyStruct : IComparable<MyStruct>
{
public int F { get; set; }
// other fields that should not affect "search"
public int X { get; set; }
public int CompareTo(MyStruct other)
{
return F.CompareTo(other.F);
}
}
Что можно назвать:
MyStruct target = new MyStruct { F = 13 };
Array.BinarySearch(arrayOfMyStruct, target);
Или отдельный IComparer<MyStruct>
:
public struct MyStruct
{
public int F { get; set; }
// other non-sort/search affecting properties
public int X { get; set; }
}
public struct MyStructComparer : IComparer<MyStruct>
{
public int Compare(MyStruct x, MyStruct y)
{
return x.F.CompareTo(y.F);
}
}
Что можно назвать как:
MyStruct target { F = 13; }
Array.BinarySearch(myArrayOfStruct, target, new MyStructComparer());
Первый имеет меньше кода, но он сильно связывает порядок с типом, что, если вы хотите изменить порядок в зависимости от ситуации (то есть разрешить несколько порядков сортировки), это не идеально. Последний дает больше гибкости в том, что вы можете предоставить несколько различных заказов независимо от структуры, но для этого требуется дополнительный класс.
UPDATE
Если вы не хотите создавать структуру dummy для сравнения, вы можете реализовать IComparable
, например:
public struct MyStruct : IComparable
{
public int F { get; set; }
// other non-sort/search affecting properties
public int X { get; set; }
public int CompareTo(object other)
{
// if the type is NOT an int, you can decide whether you'd prefer
// to throw, but the concept of comparing the struct to something
// unknown shouldn't return a value, should probably throw.
return F.CompareTo((int)other);
}
}
Что можно назвать как:
Array.BinarySearch(arrayOfMyStruct, 13);
Но, опять же, это сильно связывает вашу реализацию класса с данным типом сравнения, что, на мой взгляд, более утомительно, чем использование фиктивной цели поиска, но это мое личное предпочтение. Лично, особенно с таким коротким синтаксисом инициализатора, я предпочитаю использовать фиктивную цель:
var target = new MyStruct { F = 13 };
ОБНОВЛЕНИЕ : Вы можете поддерживать как int
, так и MyStruct
сравнений, но это быстро запутывается, поэтому я лично рекомендую снова использовать фиктивную структуру, чтобы избежать головной боли:
// implement IComparable<int> for the int search (w/o dummy), and IComparable<MyStruct> for sort
public struct MyStruct : IComparable, IComparable<MyStruct>, IComparable<int>
{
public int F { get; set; }
// other non-sort/search affecting properties
public int X { get; set; }
public int CompareTo(object other)
{
if (other is int)
return F.CompareTo((int)other);
if (other is MyStruct)
return F.CompareTo((MyStruct)other);
throw new InvalidOperationException("Other must be int or MyStruct.");
}
public int CompareTo(MyStruct other)
{
return F.CompareTo(other.F);
}
public int CompareTo(int other)
{
return F.CompareTo(other);
}
}