C#二进制搜索列表<;T>;由T的一个成员

C#二进制搜索列表<;T>;由T的一个成员,c#,search,class,binary,member,C#,Search,Class,Binary,Member,我有一个基类事件,带有日期时间成员时间戳。 许多其他事件类将由此派生 我希望能够快速搜索事件列表,因此我希望使用二进制搜索 (列表数据按时间戳排序,但同时发生的事件可能有重复的时间戳) 所以我开始写这样的东西: public class EventList<T> : List<T> where T : Event { private IComparer<T> comparer = (x, y) => Comparer<DateTime>

我有一个基类
事件
,带有
日期时间
成员
时间戳
。 许多其他事件类将由此派生

我希望能够快速搜索事件列表,因此我希望使用二进制搜索

(列表数据按时间戳排序,但同时发生的事件可能有重复的时间戳)

所以我开始写这样的东西:

public class EventList<T> : List<T> where T : Event
{
   private IComparer<T> comparer = (x, y) => Comparer<DateTime>.Default.Compare(x.TimeStamp, y.TimeStamp);

   public IEnumerable<T> EventsBetween(DateTime inFromTime, DateTime inToTime)
   {
       // Find the index for the beginning. 
       int index = this.BinarySearch(inFromTime, comparer);

       // BLAH REST OF IMPLEMENTATION
   }
}
公共类事件列表:列表,其中T:Event
{
私有IComparer comparer=(x,y)=>comparer.Default.Compare(x.TimeStamp,y.TimeStamp);
公共IEnumerable事件之间(DateTime inFomTime、DateTime inToTime)
{
//找到开头的索引。
int index=this.BinarySearch(informtime,comparer);
//空谈其余的实现
}
}
问题是BinarySearch只接受T(so-an
Event
type)作为参数,而我希望基于T的成员(TimeStamp)进行搜索


有什么好方法可以实现这一点呢?

我认为您的
比较器功能已经走上了正确的道路。它通过比较两个T的日期来比较它们

要将
INFOROMTIME
参数处理为
BinarySearch
,您可以创建一个具有正确
时间戳的伪事件,并将该伪事件传递给
BinarySearch

另外,请确保:列表是否按时间字段排序?否则binarysearch将无法工作

编辑 这个问题比我最初想的要复杂。一个有助于您的解决方案是:

  • 创建一个适配器类,将事件列表公开为IList
  • 在IList上使用BinarySearch扩展方法进行搜索
不幸的是,没有内置的,所以你必须自己写。如果您编写自己的搜索,那么将其放在扩展方法中可能不值得付出额外的努力。在这种情况下,在EventList类中自己实现自定义二进制搜索算法可能是最好的选择


另一种选择是,如果有一种形式的二进制搜索,它接受从T中提取相关键的委托,但该委托也不可用。

最简单的方法是定义一个实现
IComparer
的小型帮助器类

public class CompUtil : IComparer<T> {
  public int Compare(T left, T right) { 
    return left.TimeStamp.CompareTo(right.TimeStamp);
  }
}

如果
事件
类包含要排序的属性,那么您的方法就可以了。然后,编译器可以验证传入的任何T都将从事件继承并包含DateTime属性。如果
Event
不包含DateTime属性,您可能希望将其添加到Event,或者将T约束为更具体的类型,该类型包含搜索所需的属性

请记住,在应用BinarySearch之前,请确保列表已排序。

公共类事件列表
public class EventList<TEvent, TData>
   : List<TEvent> where TEvent : Event, TData: DataTime
{
   class Comparer : IComparer<TData> { } // as JaredPar mentioned above

   public IEnumerable<TEvent> EventsBetween(TData from, TData to) { }
}
:列出TEvent:Event、TData:DataTime的位置 { 类比较器:IComparer{}//如上面提到的JaredPar 公共IEnumerable事件介于(TData from,TData to){ }
<>代码>也许你可以考虑使用基类而不是列表。然后可以使用方法搜索指定的时间戳。该方法执行二进制搜索。

问题在于,BinarySearch没有将DateTime作为第一个参数,而是需要类型为t的对象(因此事件派生)!问题是BinarySearch没有将DateTime作为第一个参数,而是需要一个类型为t的对象(因此事件派生)!那不行。int index=this.BinarySearch(新事件(INFOROMTIME),比较器);无法工作,因为BinarySearch需要类型为t的第一个参数,该参数可以不同于(但派生自)GameEvent。我不能使用新的t(INFOROMTIME),因为派生类不支持只有参数时间戳的构造函数。请参阅我在“编辑”标题下添加的想法。这个问题乍一看很简单,但实际上并非如此。列表已排序,问题是BinarySearch方法的第一个参数…SortedList不允许重复键。
public class EventList<TEvent, TData>
   : List<TEvent> where TEvent : Event, TData: DataTime
{
   class Comparer : IComparer<TData> { } // as JaredPar mentioned above

   public IEnumerable<TEvent> EventsBetween(TData from, TData to) { }
}