1

私はこのようなものを持っています:

    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() のジェネリック型パラメーターをこれら 3 つのクラスのいずれかに制限することで、コンパイラーが何をすべきかを理解できるようになることを期待していました。

しかしwhere T : Type1, Type2, Type3、違法のようです。

これを解決するにはどうすればよいですか?

GetPageRows() のアルゴリズムは一般的であり、取得する特定の種類の行に依存しないという考え方です。戻り値の型と述語のみが T に依存します。

編集:基本型と共通の空のインターフェイスで制約を試みましたが、var filteredQueryable = GetRowsAndFilter(predicate);. 「メソッドを解決できません」。これらのメソッドの正しいバージョンを選択する方法がわかりません。どうすればいいのかわからない。GetPageRows() の一般的なアルゴリズムを、実際の型 T と、GetRowsAndFilter() の異なるバージョンにある各 T の特定の異なるクエリから分離できる必要があります。

4

3 に答える 3

2

空のインターフェイスを使用して複数の制約を回避して 1 つの制約を指定することはできますが、これでは問題は解決されませ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>()) では、タイプを指定することが、残りを正しく解決するためのドライバーです。

于 2013-05-30T13:41:37.153 に答える
1

C# では多重継承ができないためType1Type2との 1 つがType3インターフェイスでない限り、多重継承を行うことはできません。Type1Type2、の 1 つ以上がType3インターフェイスでない場合、制約を満たすことは不可能です。さらに、インターフェイスは型制約の順序で最後に来る必要があります。

あなたは言うかもしれません、待ってType3 : Type2 : Type1ください。その場合、満足するが、またはない をまだ持つことTType1できType2ますType3。したがって、この場合、それ自体Type1, Type2, Type3と同等であるため、書くことからは何も得られませんType3

于 2013-05-30T13:44:15.710 に答える
0

このように 3 つの異なる型を明示的に指定することは、直感的に間違っています。コンパイル時に、どの型を使用しているかを型安全に知るにはどうすればよいでしょうか? それらがすべて派生する共通の基本クラス、またはそれらがすべて実装するインターフェイスを定義し、ジェネリック パラメーターの型をその最小公分母に制約します。

于 2013-05-30T13:41:30.463 に答える