6

In the book C#12 In a Nutshell (p. 259 Chapter Overloading true and false), they provide us with this example to illustrate how to overload the true and false operators.

SqlBoolean a = SqlBoolean.Null;
if (a)
    Console.WriteLine ("True");
else if (!a)
    Console.WriteLine ("False");
else
    Console.WriteLine ("Null");

public struct SqlBoolean
{
    public static bool operator true (SqlBoolean x)
    {
        return  x.m_value == True.m_value;
    }

    public static bool operator false(SqlBoolean x)
    {
        return x.m_value == False.m_value;
    }

    public static SqlBoolean operator ! (SqlBoolean x)
    {
        if (x.m_value == Null.m_value) return Null;
        if (x.m_value == False.m_value) return True;
        return False;
    }

    public static readonly SqlBoolean Null = new SqlBoolean (0);
    public static readonly SqlBoolean False = new SqlBoolean (1);
    public static readonly SqlBoolean True = new SqlBoolean (2);

    SqlBoolean (byte value) { m_value = value; }
    byte m_value;
}

I'm trying to understand when the false overload is ever called, and from my understanding (and confirming it by playing with the debugger), it seems that it is never called. why would the false overload be ever useful then? Since we only ever use while (a) or while (!a), etc ... Wouldn't overloading true and ! be enough?

3
  • 3
    As an aside, note that a primary reason for the implementation of overloading true and false operators was indeed for handling tri-state logic (e.g.SQL bools that can be null)., This is now better represented with the nullable bool type, which makes overloading the true/false operators extremely unusual nowadays. Commented Sep 3, 2024 at 8:01
  • I see, the question was mainly for me to understand "what was going on under the hood", I do realize most of the "in depth" things I read about won't be commonly used. Commented Sep 3, 2024 at 8:03
  • 1
    This question is similar to: What are true and false operators in C#?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Sep 20, 2024 at 17:06

2 Answers 2

13

The C# standard has this note:

Note: Although true and false are not used explicitly in expressions (and therefore are not included in the precedence table in §12.4.2), they are considered operators because they are invoked in several expression contexts: Boolean expressions (§12.24) and expressions involving the conditional (§12.18) and conditional logical operators (§12.14). end note

Following those links, you'll find that the false operator is used in conditional logical operators:

The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. Then, if x is definitely false, the result of the operation is the value previously computed for x. Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

Here's some test code to show the various times that operators are used:

LoggingBoolean t = new LoggingBoolean(true);
LoggingBoolean f = new LoggingBoolean(false);

Console.WriteLine("Boolean expression");
if (t)
{
    Console.WriteLine("In true body");
}

if (f)
{
    Console.WriteLine("In false body");
}

Console.WriteLine("Conditional operator");

Console.WriteLine(t ? "true branch" : "false branch");
Console.WriteLine(f ? "true branch" : "false branch");

Console.WriteLine("Conditional && logic");
Console.WriteLine(t && t);
Console.WriteLine(t && f);
Console.WriteLine(f && t);
Console.WriteLine(f && f);

Console.WriteLine("Conditional || logic");
Console.WriteLine(t || t);
Console.WriteLine(t || f);
Console.WriteLine(f || t);
Console.WriteLine(f || f);

internal struct LoggingBoolean
{
    public bool Value { get; }

    public LoggingBoolean(bool value) => Value = value;

    public static bool operator false(LoggingBoolean x)
    {
        Console.WriteLine("false operator called");
        return !x.Value;
    }

    public static bool operator true(LoggingBoolean x)
    {
        Console.WriteLine("true operator called");
        return x.Value;
    }

    public static LoggingBoolean operator &(LoggingBoolean x, LoggingBoolean y) =>
        new LoggingBoolean(x.Value && y.Value);

    public static LoggingBoolean operator |(LoggingBoolean x, LoggingBoolean y) =>
        new LoggingBoolean(x.Value || y.Value);

    public override string ToString() => $"LoggingBoolean({Value})";
}

Output:

Boolean expression
true operator called
In true body
true operator called
Conditional operator
true operator called
true branch
true operator called
false branch
Conditional && logic
false operator called
LoggingBoolean(True)
false operator called
LoggingBoolean(False)
false operator called
LoggingBoolean(False)
false operator called
LoggingBoolean(False)
Conditional || logic
true operator called
LoggingBoolean(True)
true operator called
LoggingBoolean(True)
true operator called
LoggingBoolean(True)
true operator called
LoggingBoolean(False)
Sign up to request clarification or add additional context in comments.

Comments

6

False operator will come into play when there will be short circuiting involved - with && operator, when if first expression fails, we can ignore the second.

In such situation, false operator will be invoked, please see the example:

// Need to define this operator in order to leverage short circuiting with &&,
// it will be analogical with ||
public static SqlBoolean operator &(SqlBoolean left, SqlBoolean right)
{
    // Implement appropriately, this is just example
    return True;
}

And then the test:

var shortCircuitAnd = a && a;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.