我有这样的事情:
public List<T> GetPageRows<T>(Expression<Func<T, bool>> predicate, List<ColumnSortOrder> sortOrder, int pageSize, int pageNo) where T : Type1, Type2, Type3
{
var filteredQueryable = GetRowsAndFilter(predicate);
var orderedQueryable = GetOrderedQueryable(sortOrder, filteredQueryable);
var pagedQueryable = orderedQueryable.Skip((pageNo - 1) * pageSize).Take(pageSize);
return pagedQueryable.ToList();
}
private IQueryable<Type1> GetRowsAndFilter(Expression<Func<Type1, bool>> predicate)
{
return GetType1s(predicate);
}
private IQueryable<Type2> GetRowsAndFilter(Expression<Func<Type2, bool>> predicate)
{
return GetType2s(predicate);
}
private IQueryable<Type3> GetRowsAndFilter(Expression<Func<Type3, bool>> predicate)
{
return GetType3s(predicate);
}
我希望通过制作GetRowsAndFilter()的非泛型类特定版本,然后将GetPageRows()的泛型类型参数限制为这三个类中的一个,编译器能够弄清楚要做什么。
但where T : Type1, Type2, Type3
似乎是非法的。
我该如何解决这个问题?
这个想法是GetPageRows()中的算法是通用的,并不依赖于我得到的特定类型的行。只有返回类型和谓词取决于T.
编辑:我尝试限制他们的基本类型以及常见的空接口,但我仍然在var filteredQueryable = GetRowsAndFilter(predicate);
中收到错误。 “无法解决方法”。它不知道如何选择这些方法的正确版本。我不知道该怎么办。应该可以将GetPageRows()中的通用算法与实际类型T以及GetRowsAndFilter()的不同版本中每个T的特定不同查询分开。
答案 0 :(得分:2)
虽然您可以使用空接口来解决多个约束来指定一个约束,但这不能解决您的问题:无法正确解析GetRowsAndFilter
。
稍微弯曲代码之后,我想出了这个存根(我改变并剪切了东西以便编译,但你应该能够将相同的概念应用到你的代码中):
static void Main(string[] args)
{
var res = GetPageRows<Type1>(GetRowsAndFilter, t => true, null, 0, 0);
var res2 = GetPageRows<Type2>(GetRowsAndFilter, t => true, null, 0, 0);
Console.ReadLine();
}
public static List<T> GetPageRows<T>(Func<Expression<Func<T, bool>>, IEnumerable<T>> getRows, Expression<Func<T, bool>> predicate, List<int> sortOrder, int pageSize, int pageNo)
{
var filteredQueryable = getRows(predicate);
return filteredQueryable.ToList();
}
private static IEnumerable<Type1> GetRowsAndFilter(Expression<Func<Type1, bool>> predicate)
{
return Enumerable.Empty<Type1>();
}
private static IEnumerable<Type2> GetRowsAndFilter(Expression<Func<Type2, bool>> predicate)
{
return Enumerable.Empty<Type2>();
}
private static IEnumerable<Type3> GetRowsAndFilter(Expression<Func<Type3, bool>> predicate)
{
return Enumerable.Empty<Type3>();
}
您还需要提供调用的方法,否则编译器无法解析它,因为它没有足够的关于T
的类型信息,通过提供方法并使其使用相同的泛型类型方法签名,编译器至少可以确保方法正在谈论相同的T
。在调用方(GetPageRows<Type1>()
)上,指定类型是其余要正确解析的驱动程序。
答案 1 :(得分:1)
由于C#中无法进行多重继承,因此除非Type1
,Type2
和Type3
中的任何一个不是接口,否则不能这样做。如果Type1
,Type2
,Type3
中不止一个不是接口,则无法满足约束条件。此外,接口必须在类型约束的排序中排在最后。
你可能会说,等等,如果Type3 : Type2 : Type1
怎么办?在这种情况下,我们仍然可以T
满足Type1
但不满足Type2
或Type3
。因此,在这种情况下,我们从编写Type1, Type2, Type3
获得的任何内容都不会因为它本身等同于Type3
。
答案 2 :(得分:0)
明确地指定这三种不同的类型是直觉错误的:你如何知道,在编译时安全地输入类型,你正在使用哪种类型?定义它们全部派生的公共基类或它们都实现的接口,并将泛型参数类型约束到最小公分母。