Recipe 3.8 Indirectly Overloading the &&, ||, and ?: Operators
Problem
You need to control
the handling of the &&,
||, and ?: operators within
your data type; unfortunately, these operators cannot be directly
overloaded.
Solution
Overload these operators indirectly by overloading the
&, |,
true, and false
operators:
public class ObjState
{
public ObjState(int state)
{
this.state = state;
}
public int state = 0;
public static ObjState operator &(ObjState obj1, ObjState obj2)
{
if (obj1.state >= 0 && obj2.state >= 0)
return (new ObjState(1));
else
return (new ObjState(-1));
}
public static ObjState operator |(ObjState obj1, ObjState obj2)
{
if (obj1.state < 0 && obj2.state < 0)
return (new ObjState(-1));
else
return (new ObjState(1));
}
public static bool operator true(ObjState obj)
{
if (obj.state >= 0)
return (true);
else
return (false);
}
public static bool operator false(ObjState obj)
{
if (obj.state >= 0)
return (true);
else
return (false);
}
public override string ToString( )
{
return (state.ToString( ));
}
}
This technique gives you complete control over the operations of the
&&, ||, and
?: operators.
Alternatively, you can simply add an implicit conversion to
bool:
public class ObjState
{
public ObjState(int state)
{
this.state = state;
}
public int state = 0;
public static implicit operator bool(ObjState obj)
{
if (obj.state == 0)
{
throw new InvalidOperationException( );
}
return (obj.state > 0);
}
}
This technique implements strict Boolean logic; the first technique
(overriding the &&, ||,
and ?: operators) gives you more freedom to stray
from implementing strict Boolean logic.
Discussion
While you cannot overload the &&,
||, and ?: operators directly,
you can overload them indirectly by overloading the
&, |,
true, and false operators. The
&&, ||, and
?: operators then use the overloaded
&, |,
true, and false operators for
their calculations.
The && operator indirectly uses the
false and & operators to
perform a short-circuiting And operation.
Initially, the false operator is invoked to
determine whether the first object is equal to
false. If so, the operation stops and whatever is
on the lefthand side of the && operator is
returned. If the false operator returns a
true, the & operator is
invoked next to perform the ANDing operation on
the two objects. This initial test using the false
operator enables the operator to short-circuit the operation.
The || operator works the same as the
&& operator, except that the initial test
is done using the true operator rather than the
false operator.
The ?: operator only requires the overloading of
the true operator to be indirectly overloaded.
Note that overloading the true operator requires
the overloading of the false operator for
symmetry. The ?: operator takes a conditional
expression as input and evaluates either its true
or false expression. This operator can be defined
as follows:
conditional-expression ? true-expression : false-expression
The ?: operator invokes the
true operator to determine which expression of
this operator should be evaluated. Note that if an implicit
conversion to bool exists, it will be used in
preference to the true operator.
When implementing these operators, you would first check to determine
whether any parameters in the overloaded operator methods were set to
null. The code for the overloaded
& operator has been modified to do this:
public static ObjState operator &(ObjState obj1, ObjState obj2)
{
if (obj1 == null || obj2 == null)
{
throw (new ArgumentNullException("Neither object may be null."));
}
if (obj1.state >= 0 && obj2.state >= 0)
return (new ObjState(1));
else
return (new ObjState(-1));
}
See Also
See the "Operator Overloading Usage
Guidelines," "Overloadable
Operators," and "Operator
Overloading Tutorial" topics in the MSDN
documentation.
|