简体   繁体   English

C#泛型方法类型约束到几个类

[英]C# generic method type constraint to several classes

I have something like this: 我有这样的事情:

    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);
    }

I was hoping that by making the non-generic class specific versions of GetRowsAndFilter() and then restricting the generic type parameter for GetPageRows() to one of these three classes, that the compiler was able to figure out what to do. 我希望通过制作GetRowsAndFilter()的非泛型类特定版本,然后将GetPageRows()的泛型类型参数限制为这三个类中的一个,编译器能够找出该做什么。

But where T : Type1, Type2, Type3 seems to be illegal. 但是where T : Type1, Type2, Type3似乎是非法的。

How do I solve this? 我该如何解决这个问题?

The idea is that the algorithm in GetPageRows() is general and does not depend on the specific kind of rows I am getting. 我们的想法是GetPageRows()中的算法是通用的,并不依赖于我得到的特定类型的行。 Only the return type and the predicate depends on T. 只有返回类型和谓词取决于T.

EDIT: I tried constraining on their base type and also on a common empty interface, but I still get an error in the var filteredQueryable = GetRowsAndFilter(predicate); 编辑:我试图约束他们的基类型,也在一个公共空接口上,但我仍然在var filteredQueryable = GetRowsAndFilter(predicate);得到一个错误var filteredQueryable = GetRowsAndFilter(predicate); . "Cannot resolve method". “无法解决方法”。 It doesn't know how to choose the right version of these methods. 它不知道如何选择这些方法的正确版本。 I don't know what to do. 我不知道该怎么办。 It should be possible to separate the general algorithm in GetPageRows() from the actual type T and the specific, different queries for each T that is in the different versions of GetRowsAndFilter(). 应该可以将GetPageRows()中的通用算法与实际类型T以及不同版本的GetRowsAndFilter()中的每个T的特定不同查询分开。

Although you can get around multiple constraints using empty interfaces to specify one constraint, this won't solve your issue: not resolving GetRowsAndFilter correctly. 虽然您可以使用空接口来解决多个约束以指定一个约束,但这不会解决您的问题:无法正确解析GetRowsAndFilter

After bending the code a little, I came up with this stub (I changed and cut stuff out to get it to compile, but you should be able to apply the same concept to your code): 稍微弯曲代码之后,我想出了这个存根(我改变并剪切了东西以使其编译,但你应该能够将相同的概念应用于你的代码):

    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>();
    }

You need to also provide the method to call otherwise the compiler can't resolve it because it doesn't have enough type information about T , by supplying the method and having it use the same generic type in the method signature, the compiler can at least ensure the methods are talking about the same T . 您还需要提供调用方法,否则编译器无法解析它,因为它没有足够的关于T类型信息,通过提供方法并使其在方法签名中使用相同的泛型类型,编译器可以在至少确保方法是在谈论相同的T On the calling side ( GetPageRows<Type1>() ), specifying the type is the driver for the rest to resolve correctly. 在调用端( GetPageRows<Type1>() ),指定类型是其余要正确解析的驱动程序。

Since multiple inheritance isn't possible in C#, you can't do that unless at most one of Type1 , Type2 and Type3 are not interfaces. 由于在C#中不可能进行多重继承,因此除非Type1Type2Type3中的任何一个不是接口,否则不能这样做。 If more than one of Type1 , Type2 , Type3 were not interfaces, it would be impossible to ever satisfy the constraint. 如果Type1Type2Type3中不止一个不是接口,那么就不可能满足约束条件。 Additionally, the interfaces must come last in the ordering of the type constraints. 此外,接口必须在类型约束的排序中排在最后。

You might say, wait, what if Type3 : Type2 : Type1 ? 你可能会说,等等,如果Type3 : Type2 : Type1 In that you case we can still have a T that satifies Type1 but not Type2 nor Type3 . 在你的情况下,我们仍然可以有一个满足Type1但不满足Type2Type3T So in this case we gain nothing from writing Type1, Type2, Type3 as it's equivalent to Type3 by itself. 所以在这种情况下,我们从写入Type1, Type2, Type3获得的东西Type1, Type2, Type3因为它本身就等同于Type3

Specifying the three different types explicitly like that is intuitively wrong: how would you know, type-safely, at compile time, which type you're working with? 明确地指定这三种不同的类型是直觉错误的:你怎么知道,在编译时安全地键入,你正在使用哪种类型? Define a common base class from which they all derive or an interface which they all implement and constrain the generic parameter type to that lowest common denominator. 定义它们全部派生的公共基类或它们都实现的接口,并将泛型参数类型约束到最小公分母。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM