DekGenius.com
[ Team LiB ] Previous Section Next Section

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.

    [ Team LiB ] Previous Section Next Section