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

前端 未结 3 1650
悲&欢浪女
悲&欢浪女 2020-12-06 05:06

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

public static class Extensions
{
    public static TableType DoSomething&         


        
相关标签:
3条回答
  • 2020-12-06 05:47

    Eric's answer is great for explaining why the types cannot be inferred. Here are a couple of suggestions to hopefully cut down on the verbosity of the code that you will have to write.

    If you can explicitly define the type of your lambda expression, then it can infer the types.

    One example of how to do that is below. I've created a criteria parameter that is explicitly of type Expression<Func<MyTypedDataSet.MyTypedRow, bool>>. In this example, this doesn't save you much typing, but perhaps in practice you can make use of this.

            MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
    
            Expression<Func<MyTypedDataSet.MyTypedRow, bool>> criteria = row => row.Field1 == "foo";
    
            return table.DoSomething(criteria);
    

    EDIT: altered my example to use another extension method rather than deriving a custom TypedTableBase<T> class from System.Data.TypedTableBase<T>.

    Below is another example that can do a better job of inferring the type parameters. You define another extension method (mine is called RowPredicate) that only has one type parameter to infer. The first parameter is of type TypedTableBase<RowType>, so the compiler should have no problem inferring the type from that:

        public static Expression<Func<RowType, bool>> RowPredicate<RowType>(this TypedTableBase<RowType> table, Expression<Func<RowType, bool>> predicate)
            where RowType : DataRow
        {
            return predicate;
        }
    

    This allows you to compile the following code:

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

    Primarily the table parameter simply servers to inform the compiler of the type to use for RowType. Is this a good idea? I'm not so sure, but it does allow the compiler to infer all of the generic types.

    0 讨论(0)
  • 2020-12-06 05:54

    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.

    0 讨论(0)
  • 2020-12-06 06:00

    Even if that wasn't ideal, I gave up trying to return anything at all which allows me to do something like the following:

    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
        }
    

    And then use it like so:

    MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
    table.DoSomething(row => row.Field1 == "foo"));
    

    and the compiler infers the type correctly.

    Thank you both for your answers.

    0 讨论(0)
提交回复
热议问题