Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does "operator true" in c# have exactly two places it can be used?

c# lets you override "operator true" and "operator false" for a class:

class Foo
{
   bool Thing;

   Foo(bool thing)
   {
      Thing = thing;
   }

   public static bool operator true(Foo foo) => foo.Thing;
   public static bool operator false(Foo foo) => !foo.Thing;
}

and it sort of works. You can say

Foo foo = new Foo(true);
if (foo)
   Stuff();
string s = foo ? "yes" : "no";

But you can't say

Foo foo = new Foo(true);
bool boo = true;
if (boo && foo)
   Stuff();
if (boo & foo)
   Stuff();
if (boo & (foo == true))
   Stuff();
if (boo & ((bool)foo))
   Stuff();
Foo foo2 = new Foo(true);
if (foo && foo2)
   Stuff();
if (foo & foo2)
   Stuff();
if (foo == boo)
   Stuff();
if (foo != boo)
   Stuff();
bool boo2 = foo;

In every case the compiler complains.

Does the c# compiler use "operator true" and "operator false" anywhere except for those very specific syntaxes?

EDIT

I found one more place where "operator true" and "operator false" work. If you define an "operator&" that returns Foo in addition to the true and false operators, the compiler will take an expression "foo1 && foo2" and pretend you wrote "foo1 & foo2" and so call your overridden operator. In other words, the existence of "operator true" and "operator false" change the compiler's behavior even though it never calls those operators.

like image 685
Betty Crokker Avatar asked Mar 13 '20 17:03

Betty Crokker


People also ask

Is the operator true?

The true operator returns the bool value true to indicate that its operand is definitely true. The false operator returns the bool value true to indicate that its operand is definitely false. The true and false operators are not guaranteed to complement each other.

What are the operators that give result as true or false?

Boolean Operators include AND, OR, XOR, or NOT and can have one of two values, true or false.

Is false in C#?

In C# true and false are boolean literals. They are values that mean yes and no. They can be stored in variables of type bool.

How do you make a true or false statement in C#?

The & operator produces true only if both its operands evaluate to true . If either x or y evaluates to false , x & y produces false (even if another operand evaluates to null ). Otherwise, the result of x & y is null . The | operator produces false only if both its operands evaluate to false .


2 Answers

Does “operator true” in c# have exactly two places it can be used?

Not exactly. You can search on the C# Language Specification for "operator true" (I did) and see what it does. Sections 7.12.2, 7.14, 7.20 mentions it. 7.14 essentially is about the ternary operator which you already know about, but in 7.20, it says

A boolean-expression is an expression that yields a result of type bool; either directly or through application of operator true in certain contexts as specified in the following.

The controlling conditional expression of an if-statement (§8.7.1), while-statement (§8.8.1), do-statement (§8.8.2), or for-statement (§8.8.3) is a boolean-expression.

So, not just in an if statement, but also in a while, do, for as well.

In 7.12.2, it says:

When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following must be true, where T is the type in which the selected operator is declared:

  • The return type and the type of each parameter of the selected operator must be T. In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T.
  • T must contain declarations of operator true and operator false.

So && can be used on your custom type if you also declare &.


EDIT:

Just found this link, which sums it up very clearly.


In other words, the existence of "operator true" and "operator false" change the compiler's behavior even though it never calls those operators.

It does call these operators. As per the language spec 7.12.2:

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.

Basically, since && is short-circuiting, it has to know whether one of its operand is false, by using the false operator.

so why did the language designers create "operator true" and "operator false"?

It's explained pretty well here, I think:

The true operator returns the bool value true to indicate that its operand is definitely true. The false operator returns the bool value true to indicate that its operand is definitely false.

It's basically for situations where you want your custom type to have a truthy/falsey value. The LaunchStatus type in the same link and the DBBool type here are good examples of this.

like image 147
Sweeper Avatar answered Oct 09 '22 03:10

Sweeper


If you wanted all of those conditional statements to compile, then you need to implement more operators in addition to true and false. You could get them all to work with this implementation:

public class Foo
{
    bool Thing;

    public Foo(bool thing)
    {
        Thing = thing;
    }

    public static bool operator true(Foo foo) => foo;
    public static bool operator false(Foo foo) => !foo;
    public static implicit operator bool(Foo foo) => foo?.Thing ?? false;
    public static implicit operator Foo(bool b) => new Foo(b);
    public static Foo operator &(Foo left, Foo right) => (left?.Thing & right?.Thing) ?? false;
    public static Foo operator |(Foo left, Foo right) => (left?.Thing | right?.Thing) ?? false;
}

Now, if you were to remove the true and false operators, you would see that the short-circuit operations, if(boo && foo) and if(foo && foo2) would no longer compile. As @Sweeper wrote in his answer, those operators are necessary in order to get short-circuited expressions to compile.

like image 4
Jonathon Chase Avatar answered Oct 09 '22 04:10

Jonathon Chase