In the comments to “Get Rid of out Parameters,” a reader mentioned a technique that I neglected to cover: the functional continuation-passing style. Here’s how Ram presented it.
static void Main()
{
Div(16, 3, (quotient, reminder) =>
{
Console.WriteLine("quotient: {0}", quotient);
Console.WriteLine("remainder: {0}", reminder);
});
}
static void Div(int dividend, int divisor, Action<int, int> done)
{
Contract.Requires(divisor != 0);
var quotient = dividend / divisor;
var remainder = dividend % divisor;
if (done != null)
done(quotient, remainder);
}
In the article’s examples, an assumption was being made that the method needed to return the quotient and remainder of a div operation. The program would then continue to to run, utilizing the return values of the operation. The style Ram brought up reverses the program flow by injecting the code that utilizes the return values. Rather devious in my opinion.
Here’s my version, using a function rather than a method. I’m also using my own coding style and naming conventions.
static void Main()
{
Action<int, int, Action<int, int>> div = (dividend, divisor, action) =>
{
Contract.Requires(divisor != 0);
var quotient = dividend / divisor;
var remainder = dividend % divisor;
if (action != null)
{
action(quotient, remainder);
}
};
div(16, 3, (quotient, reminder) =>
{
Console.WriteLine("quotient: {0}", quotient);
Console.WriteLine("remainder: {0}", reminder);
});
}
This is the same thing as Ram’s version, except it’s an action that can be passed around. What if we make it a Func and use generics?
static void Main()
{
var foo = Div(16, 3, (q, r) => q * r);
Console.WriteLine(foo);
}
public static T Div<T>(int dividend, int divisor, Func<int, int, T> func)
{
Contract.Requires(divisor != 0);
Contract.Requires(func != null);
var quotient = dividend / divisor;
var remainder = dividend % divisor;
return func(quotient, remainder);
}
To get the generic type inference, it had to be switched back to a method. It turns out that using Func makes it possible to use anonymous types without resorting to the dynamic keyword.
static void Main()
{
var result = Div(16, 3, (q, r) => new { Quotient = q, Remainder = r });
Console.WriteLine("quotient: {0}", result.Quotient);
Console.WriteLine("remainder: {0}", result.Remainder);
}
public static T Div<T>(int dividend, int divisor, Func<int, int, T> func)
{
Contract.Requires(divisor != 0);
Contract.Requires(func != null);
var quotient = dividend / divisor;
var remainder = dividend % divisor;
return func(quotient, remainder);
}
I believe this to be the best solution as there is type safety and a functional inversion of control. Why should someone be forced to use a DivResult class when they may not need one?