2010-09-02 41 views
13

我试图创建一个通用的扩展方法,即在输入数据表的工作原理:通用扩展方法:类型参数不能从使用推断

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看到。

感谢

回答

19

方法类型推断不会使从参数推论约束。它从参数推断到形式参数,然后检查从形式参数中得出的推论是否满足约束条件。

你的情况不存在从参数足够的数据来推断类型参数是什么,而不首先看的限制,这我们不打算这样做直到我们检查推论反对限制。对此很抱歉,但这是指定类型推断算法的方式。

我已经被问过这么多次的问题,而且我的共识似乎是道德上错误的,因为我坚持认为推理应该从论据中仅依据形式参数来推论。有关十几人告诉我,我判断错误在这方面,看到了评论我的这个密切相关的问题的分析:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

我坚持我的立场。

+3

我很害怕那个......谢谢你的回答 – 2010-09-02 19:14:59

+1

你是对的:) – Brian 2010-09-02 21:43:38

0

埃里克的答案很好解释为什么不能推断类型。以下是一些建议,希望能够减少您必须编写的代码的详细程度。

如果您可以明确定义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。这是一个好主意吗?我不太确定,但它确实允许编译器推断所有的泛型类型。

0

即使这是不理想,我放弃了试图在所有的巫婆返回任何东西可以让我做这样的事情:

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

和编译器推断正确的类型...

谢谢你们的答案。

相关问题