Does "operator true" in c# have exactly two places it can be used?
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 operatortrue
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), orfor-statement
(§8.8.3) is aboolean-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, whereT
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 typeT
, and must return a result of typeT
.T
must contain declarations of operatortrue
and operatorfalse
.
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 asT.false(x) ? x : T.&(x, y)
, whereT.false(x)
is an invocation of the operatorfalse
declared inT
, andT.&(x, y)
is an invocation of the selected operator&
. In other words,x
is first evaluated and operatorfalse
is invoked on the result to determine ifx
is definitelyfalse
. Then, ifx
is definitelyfalse
, the result of the operation is the value previously computed forx
. Otherwise,y
is evaluated, and the selected operator&
is invoked on the value previously computed forx
and the value computed fory
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 valuetrue
to indicate that its operand is definitely true. Thefalse
operator returns the bool valuetrue
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.
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.