Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic extension method : Type argument cannot be inferred from the usage

I'm trying to create a generic extension method, that works on typed data tables :

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

The first line works fine, but it's really ugly...
The second line doesn't compile because the compiler cannot infer the type of RowType.
This is a method that will be used as part of a DataLayer by many different programmers, so I would rather not need them to specify the TypeParameter.
Shouldn't the compiler know that RowType is the same type as the one that was used by TypedTableBase ?

For different reasons that may not be obvious in this code sample, I really need to return the datatable in its original form. And the reason I need RowType is so the 'Expression<Func<T, bool>>' will be typed and seen by InteliSence.

Thanks

like image 845
Pierre-Olivier Goulet Avatar asked Sep 02 '10 18:09

Pierre-Olivier Goulet


1 Answers

Method type inference does not make inferences from arguments to constraints. It makes inferences from arguments to formal parameters and then checks whether the inferences made from the arguments to the formals satisfy the constraints.

In your case there is not enough data from the arguments to deduce what the type parameters are without first looking at the constraints, which we're not going to do until we check the inferences against the constraints. Sorry about that, but that's how the type inference algorithm is specified.

I've been asked questions about this many times and the consensus seems to be that I am morally wrong for maintaining the position that inference should infer from arguments to formal parameters alone. For about a dozen people telling me I'm wrongheaded in this regard, see the comments to my analysis of this closely related issue:

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

I maintain my position.

like image 127
Eric Lippert Avatar answered Sep 27 '22 19:09

Eric Lippert