C# 泛型扩展方法:无法从用法推断类型参数

C# 泛型扩展方法:无法从用法推断类型参数,c#,database,generics,lambda,C#,Database,Generics,Lambda,我正在尝试创建一个通用扩展方法,该方法适用于类型化数据表: public static class Extensions { public static TableType DoSomething<TableType, RowType>(this TableType table, param Expression<Func<RowType, bool>>[] predicates) where TableType : TypedTabl

我正在尝试创建一个通用扩展方法,该方法适用于类型化数据表:

public static class Extensions
{
    public static TableType DoSomething<TableType, RowType>(this TableType table, param Expression<Func<RowType, bool>>[] predicates)
        where TableType : TypedTableBase<RowType>
        where RowType : DataRow
    {
        // do something to each row of the table where the row matches the predicates
        return table;
    }

    [STAThread]
    public static void main()
    {
        MyTypedDataSet.MyTypedDataTable table = getDefaultTable();
    }

    public static MyTypedDataSet.MyTypedDataTable getDefaultTable()
    {
        // this line compiles fine and does what I want:
        return new MyTypedDataSet.MyTypedDataTable().DoSomething<MyTypedDataSet.MyTypedDataTable, MyTypedDataSet.MyTypedRow>(row => row.Field1 == "foo");

        // this line doesn't compile :
        return new MyTypedDataSet.MyTypedDataTable().DoSomething(row => row.Field1 == "foo");
        // Error : The type arguments .. cannot be inferred from the usage
    }
}
公共静态类扩展
{
公共静态TableType DoSomething(此TableType表,参数表达式[]谓词)
其中TableType:TypedTableBase
其中RowType:DataRow
{
//对表中与谓词匹配的每一行执行某些操作
返回表;
}
[状态线程]
公共静态void main()
{
MyTypedDataSet.MyTypedDataTable=getDefaultTable();
}
公共静态MyTypedDataSet.MyTypedDataTable getDefaultTable()
{
//这行代码编译得很好,可以满足我的要求:
返回新的MyTypedDataSet.MyTypedDataTable().DoSomething(row=>row.Field1==“foo”);
//此行不编译:
返回新的MyTypedDataSet.MyTypedDataTable().DoSomething(row=>row.Field1==“foo”);
//错误:无法从用法推断类型参数
}
}
第一行很好,但它真的很难看…
第二行未编译,因为编译器无法推断RowType的类型。
这是一种将由许多不同的程序员作为数据层的一部分使用的方法,因此我不希望他们指定TypeParameter。
编译器不应该知道RowType与TypedTableBase使用的类型相同吗

由于在这个代码示例中可能不明显的不同原因,我确实需要以原始形式返回datatable。我需要RowType的原因是,InteliSence将键入并查看“表达式


感谢

方法类型推理不会从参数到约束进行推理。它从参数到形式参数进行推理,然后检查从参数到形式参数的推理是否满足约束

在您的例子中,没有足够的数据从参数中推断出类型参数是什么,而不首先查看约束,这是我们在对照约束检查推断之前不会做的。对此很抱歉,但类型推断算法就是这样指定的

关于这一点,我已经被问了很多次,大家一致认为,我坚持推理应该仅从论点到形式参数进行推断的立场在道德上是错误的。关于十几个人告诉我在这方面我是错误的,请参阅我对这一密切相关问题的分析评论:


我坚持我的立场。

埃里克的回答很好地解释了为什么不能推断这些类型。下面是一些建议,希望能减少您必须编写的代码的冗长程度

如果可以显式定义lambda表达式的类型,那么它可以推断出类型

下面是如何做到这一点的一个例子。我创建了一个
criteria
参数,该参数的类型明确为
Expression
。在本例中,这不会为您节省太多的键入时间,但在实践中,您可能可以利用这一点

        MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();

        Expression<Func<MyTypedDataSet.MyTypedRow, bool>> criteria = row => row.Field1 == "foo";

        return table.DoSomething(criteria);
这允许您编译以下代码:

        MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();

        return table.DoSomething(table.RowPredicate(row => row.Field1 == "foo"));

主要是
参数只是通知编译器要用于
行类型
的类型。这是个好主意吗?我不太确定,但它确实允许编译器推断所有泛型类型。

即使这并不理想,我也放弃了返回任何允许我执行以下操作的内容:

public static void DoSomething<RowType>(this TypedTableBase<RowType> table, param Expression<Func<RowType, bool>>[] predicates)
    where RowType : DataRow
    {
        // do something to each row of the table where the row matches the predicates
        // do not return the table... too bad for chaining commands
    }
并且编译器正确地推断出类型


谢谢你们的回答。

这是过期链接的回程机器版本:
public static void DoSomething<RowType>(this TypedTableBase<RowType> table, param Expression<Func<RowType, bool>>[] predicates)
    where RowType : DataRow
    {
        // do something to each row of the table where the row matches the predicates
        // do not return the table... too bad for chaining commands
    }
MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
table.DoSomething(row => row.Field1 == "foo"));