Reputation: 9497
Below a Compose
function. If f
and g
are unary functions which return values, then Compose(f,g)
returns a function which when called on x
performs the equivalent to f(g(x))
.
static Func<X, Z> Compose<Z, Y, X>(Func<Y, Z> f,Func<X, Y> g)
{ return x => f(g(x)); }
Here's a couple of simple Func
values which can be composed:
Func<int, bool> is_zero = x => { return x == 0; };
Func<int, int> mod_by_2 = x => { return x % 2; };
E.g. this works:
Console.WriteLine(Compose(is_zero, mod_by_2)(4));
However, if I instead have these equivalent static methods:
static bool IsZero(int n) { return n == 0; }
static int ModBy2(int n) { return n % 2; }
the same example doesn't work with those. I.e. this produces a compile time error:
Console.WriteLine(Compose(IsZero, ModBy2)(4));
Explicitly passing types to Compose
fixes the issue:
Console.WriteLine(Compose<bool, int, int>(IsZero, ModBy2)(4));
Is there anyway to write Compose
such that it works on the static methods without the explicit types?
Is this a good approach to take to implementing Compose
? Can anyone make improvements to this?
Upvotes: 9
Views: 2400
Reputation: 754525
The problem here is not the use of static
methods but the use of method groups. When you use a function name as an expression without invoking it then it's a method group and must go through method group conversion. You would have the exact same problem with instance methods.
The problem you're running into is that C# can't do return type inference on method groups. Using Compose(IsZero, ModBy2))
requires the return type to be inferred for both IsZero
and ModBy2
and hence this operation fails.
This is a known limitation in the inference capabilities of the C# compiler. Eric Lippert wrote an extensive blog article on this particular subject which covers this problem in detail
Upvotes: 10