The problem with your MyDouble
wrapper class is that you use it by calling longOperation
directly. As *
is not short circuiting, it will be called directly.
Instead, you could just make your wrapper accept a Func<double>
as the second parameter instead of the double value itself. So it would work like the ShortCircuitMultiply
function:
public static MyDouble operator *(MyDouble left, Func<double> right)
{
return Math.Abs(left.value) < epsilon ? new MyDouble(0) : new MyDouble(left.value * right());
}
Then you would use it like this:
MyDouble x = 0;
Console.WriteLine(x * LongOperation);
And even chaining works:
MyDouble x = 5;
Console.WriteLine(x * OperationReturingZero * LongOperation);
Full example
class Program
{
static void Main()
{
MyDouble x = 0;
Console.WriteLine(x * LongOperation);
MyDouble y = 5;
Console.WriteLine(y * OperationReturningZero * LongOperation);
Console.ReadLine();
}
private static double LongOperation()
{
Console.WriteLine("LongOperation");
return 5;
}
private static double OperationReturningZero()
{
Console.WriteLine("OperationReturningZero");
return 0;
}
}
class MyDouble
{
private static double epsilon = 0.00000001;
private double value;
public MyDouble(double value)
{
this.value = value;
}
public static MyDouble operator *(MyDouble left, Func<double> right)
{
Console.WriteLine("* (MyDouble, Func<double>)");
return Math.Abs(left.value) < epsilon ? new MyDouble(0) : new MyDouble(left.value * right());
}
public static MyDouble operator *(MyDouble left, MyDouble right)
{
Console.WriteLine("* (MyDouble, MyDouble)");
return new MyDouble(left.value * right.value);
}
public static implicit operator double(MyDouble myDouble)
{
Console.WriteLine("cast to double");
return myDouble.value;
}
public static implicit operator MyDouble(double value)
{
Console.WriteLine("cast to MyDouble");
return new MyDouble(value);
}
}
Output:
cast to MyDouble
* (MyDouble, Func<double>)
cast to double
0
cast to MyDouble
* (MyDouble, Func<double>)
OperationReturningZero
* (MyDouble, Func<double>)
cast to double
0