2010-12-20 41 views
0

我正在使用一个库(在Gtk中的TreeView是具体的),它允许你通过传递一个比较两行的函数来进行排序。函数签名的简化版本,可能是这样的:如何使这种通用方法更加灵活?

int SomeSortFunc (Foo foo1, Foo foo2) 
{ 
    // Return -1 if foo1 < foo2, 0 if foo1 == foo2, 1 if foo1 > foo2 
} 

我不能简单地实现Foo.CompareTo (Foo),因为我要排序不同,这取决于上下文。我排序的Foo中有几个字段。每个字段的排序优先级取决于上下文。我想编写这样的事:

int SortFunc<T> (Foo foo1, Foo foo2, params Func<Foo, T> [] selectors) 
    where T : IComparable<T> 
{ 
    return selectors 
     .Select (s => s (foo1).CompareTo (s (foo2))) 
     .FirstOrDefault (i => i != 0); 
} 

// Compare by SomeString, then by SomeInt, then by SomeBar 
int SomeSortFunc (Foo foo1, Foo foo2) 
{ 
    // Won't compile, because String, Int, and Bar are all different types. 
    return SortFunc (foo1, foo2, f => f.SomeString, f => f.SomeInt, f => f.SomeBar); 
} 

这不会编译,因为在Func<Foo, T>TStringIntBar : IComparable<Bar>(换句话说不同,是没有办法解决的TSortFunc<T>)。

有没有什么办法可以写这个函数,让每个选择器都可以返回一个不同的类型,只要每个类型SomeType实现了IComparable<SomeType>

回答

3

我会简化它,只是接受函数返回非泛型IComparable。现在你可以传递返回原语的函数,而不需要知道你的函数实际需要的泛型类型参数的数量,因为它真的需要每个提供函数的类型参数。

int SortFunc(Foo foo1, Foo foo2, params Func<Foo, IComparable>[] selectors) 
+0

啊,这样做很有道理,似乎完美地工作。我失去了一点安全性,但这绝对是值得的。 – 2010-12-20 22:23:51