[英]Generic extension method : Type argument cannot be inferred from the usage
我正在尝试创建一个适用于类型化数据表的通用扩展方法:
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
}
}
第一行工作正常,但它真的很难看......
第二行不编译因为编译器不能推断ROWTYPE的类型。
这是一种将被许多不同程序员用作 DataLayer 的一部分的方法,因此我宁愿不需要他们指定 TypeParameter。
如果不是编译器知道ROWTYPE是同类型已使用的TypedTableBase的人吗?
由于在此代码示例中可能不明显的不同原因,我确实需要以原始形式返回数据表。 我需要RowType的原因是'Expression <
Func <
T, bool> >
' 将被 InteliSence 输入和看到。
谢谢
方法类型推断不会从参数到约束进行推断。 它从参数到形式参数进行推断,然后检查从参数到形式参数所做的推断是否满足约束。
在您的情况下,没有足够的参数数据来推断类型参数是什么,而无需先查看约束,在我们检查对约束的推断之前,我们不会这样做。 对此很抱歉,但这就是指定类型推断算法的方式。
我已经多次被问到这个问题,共识似乎是,我坚持推理应该仅从参数到形式参数进行推断的立场在道德上是错误的。 对于大约十几个人告诉我我在这方面的错误,请参阅我对这个密切相关问题的分析的评论:
我保持我的立场。
Eric 的回答非常适合解释为什么不能推断类型。 这里有一些建议,希望能减少您必须编写的代码的冗长。
如果您可以明确定义 lambda 表达式的类型,则它可以推断类型。
下面是如何做到这一点的一个示例。 我创建了一个明确类型为Expression<Func<MyTypedDataSet.MyTypedRow, bool>>
的criteria
参数。 在此示例中,这不会为您节省太多输入,但也许在实践中您可以利用它。
MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
Expression<Func<MyTypedDataSet.MyTypedRow, bool>> criteria = row => row.Field1 == "foo";
return table.DoSomething(criteria);
编辑:更改我的示例以使用另一种扩展方法,而不是从System.Data.TypedTableBase<T>
派生自定义TypedTableBase<T>
类。
下面是另一个可以更好地推断类型参数的示例。 您定义了另一种扩展方法(我的称为RowPredicate
),它只有一个类型参数可供推断。 第一个参数的类型为TypedTableBase<RowType>
,因此编译器从它推断类型应该没有问题:
public static Expression<Func<RowType, bool>> RowPredicate<RowType>(this TypedTableBase<RowType> table, Expression<Func<RowType, bool>> predicate)
where RowType : DataRow
{
return predicate;
}
这允许您编译以下代码:
MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
return table.DoSomething(table.RowPredicate(row => row.Field1 == "foo"));
主要是table
参数只是用于通知编译器要用于RowType
的类型。 这是一个好主意吗? 我不太确定,但它确实允许编译器推断所有泛型类型。
即使这并不理想,我也放弃了尝试返回任何允许我执行以下操作的任何内容:
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"));
并且编译器正确推断类型。
谢谢你们的回答。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.