c# - How to make multiplication operator (*) behave as short-circuit? -


i have lots of computations, specially multiplication, first part 0 , don't want evaluate second operand in case. there @ least 2 short-circuit operators in c#: && , || evaluate second operand if necessary. want achieve similar behavior multiplication operator.

in .net can't overload && operator directly, can overload & , false operators, can use extension points change behavior of short-circuit operator. can find more details @ article c# operator overloading: ‘&&’ operator

is there means achieve or similar behavior multiplication operator?

this pure syntax question, because implementation simple. next method achieves want in terms of functionality:

public static double shortcircuitmultiply(double val, func<double> anothervalue) {     var epsilon = 0.00000001;     return math.abs(val) < epsilon ? 0 : val * anothervalue(); } 

note: implementation not full: in c# if multiply 0.0 double.nan or double.negativeinfinity or double.positiveinfinity, you'll nan, in terms of shortcircuitmultiply - zero. let's ignore detail , it's irrelevant in domain.

so if call shortcircuitmultiply(0.0, longoperation) longoperation func<double>, last term won't evaluated , result of operation zero.

the problem is, stated, have lots of shortcircuitmultiply calls , want make code more readable. want code similar 0.0 * longoperation() if possible.


another note: i've tried build wrapper on double , create implicit casting double , overload * operator. understand, redundant: wanted acheive readability, trying build yet wrapper. anyway, next code demonstrates intent:

class mydouble {     double value;     public mydouble(double value)     {         this.value = value;      }      public static mydouble operator *(mydouble left, mydouble right)      {         console.writeline ("* operator call");         return new mydouble(left.value * right.value);     }      public static implicit operator double(mydouble mydouble)     {         console.writeline ("cast double");         return mydouble.value;     }      public static implicit operator mydouble(double value)     {         console.writeline ("cast mydouble");         return new mydouble(value);     } } 

now if go with:

mydouble 0 = 0;  console.writeline (zero * longoperation()); //longoperation still func<double> 

i've receive:

cast mydouble             called longoperation        <-- want avoid (it's printed longoperation body) cast double              cast mydouble * operator call cast double    0 

but can see, longoperation evaluated long before overloaded operator called, , can't substitute 1 of parameters func or expression make lazy.

the problem mydouble wrapper class use calling longoperation directly. * not short circuiting, called directly.

instead, make wrapper accept func<double> second parameter instead of double value itself. work 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 use this:

mydouble x = 0; console.writeline(x * longoperation); 

and 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 double");         return mydouble.value;     }      public static implicit operator mydouble(double value)     {         console.writeline("cast mydouble");         return new mydouble(value);     } } 

output:

cast mydouble * (mydouble, func<double>) cast double 0 cast mydouble * (mydouble, func<double>) operationreturningzero * (mydouble, func<double>) cast double 0 

Comments

Popular posts from this blog

Perl - how to grep a block of text from a file -

delphi - How to remove all the grips on a coolbar if I have several coolbands? -

javascript - Animating array of divs; only the final element is modified -