3
votes

In the below code block, I've numbered four lines within Main. Here are my questions/comments on them:

  1. Will not compile because Squared is not a Func<T, R> (expected).
  2. Will compile because squared is a Func<T, R> (expected).
  3. Produces the following compiler error:

    The type arguments for method 'ConsoleApplication1.FunctionExt.DelegateOf<T,R>(System.Func<T,R>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

  4. Produces the same kind of error:

    The type arguments for method 'ConsoleApplication1.FunctionExt.ForwardCompose<T1,T2,R>(System.Func<T1,T2>, System.Func<T2,R>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

I'd appreciate an explanation for why the errors in 3 and 4 occur.

public static class FunctionExt
{
    public static Func<T, R> DelegateOf<T, R>(Func<T, R> func)
    {
        return func;
    }

    public static Func<T1, R> ForwardCompose<T1, T2, R>(this Func<T1, T2> func1, Func<T2, R> func2)
    {
        return x => func2(func1(x));
    }
}

public class Program
{
    static int Squared(int n)
    {
        return n * n;
    }

    static int Plus5(int n)
    {
        return n + 5;
    }

    static Func<int, int> squared = Squared;

    public static void Main()
    {
        // 1
        Squared.ForwardCompose(Plus5);

        // 2
        squared.ForwardCompose(Plus5);

        // 3
        FunctionExt.DelegateOf(Squared).ForwardCompose(Plus5);

        // 4
        FunctionExt.ForwardCompose(Squared, Plus5);
    }
}
1
I have just added the generic types to the line 3 and 4 and it is compling I hope will this solve your problem.Bassam Alugili
It seems to me that the problem is that generic arg type inference stumbles because Squared is a method group (in contrast to squared which is a delegate) and as such does not have a fixed signature to help with inference.Jon
@Jon Yes, clearly the difference here is between a delegate and a method group. In this case though the method group is of size one, so technically the type could be inferred, although the C# compiler doesn't do so. I just don't understand the type inference rules thoroughly enough to explain why it doesn't.Servy
In trying to find an answer for this, I found this discussion thread which was enlighteningSven Grosen

1 Answers

0
votes

This compiles:

    // 1
    squared.ForwardCompose(Plus5);

    // 2
    squared.ForwardCompose(Plus5);

    // 3
    FunctionExt.DelegateOf(squared).ForwardCompose(Plus5);

    // 4
    FunctionExt.ForwardCompose(squared, Plus5);