您可以为您的结构实现 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());
第一个代码较少,但它将排序与类型强烈耦合,如果您想根据情况更改排序(即允许多个排序顺序),这并不理想。后者提供了更大的灵活性,您可以独立于结构提供多个不同的顺序,但它确实需要一个额外的类。
更新
如果你不想创建一个 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);
}
}