1

According to the C# Language Specification:

The true and false unary operators require pair-wise declaration. A compile-time error occurs if a class declares one of these operators without also declaring the other.

This seems like a strange choice, since these two opeators, despite having names that seem related, have distinct uses.

Complete list of uses for operator true:

  1. It allows the type to be used instead of a bool in an if, while, do, or for statement, and as a first operand to the ternary ? : operator. (Relevant only if the type does not also have a matching implicit conversion implicit operator bool.)
  2. If the same struct/class overloads the operator | in an appropriate way, it allows the use of short-circuiting operator || as well.

Complete list of uses for operator false:

  • If the same struct/class overloads the operator & in an appropriate way, it allows the use of short-circuiting operator && as well.

Note that operator false is only meaningful if operator & is overloaded by the same type. Never is operator false relevant for if, while etc. If you want to "negate" instances of your type, overload unary operator ! ("not") instead.

So there seem to be legitimate uses where you need operator true but not operator false, or vice versa.

For example if I need only use (1) above, I overload operator true (and possibly operator ! as well). But I might not want to overload &, so it is meaningless to have to write the operator false.

And in the opposite direction, I may design a type where I can & instances together, and there may be a use of a short-circuit && as well, use (•), so I would overload operator false. But that does not necessarily mean I want my type to have | and ||, much less that I require my type to be usable inside an if, while, etc.

There is no requirement to overload | and & "pairwise".

Instead of the actual restriction, it would be much more useful to specify:

(hypothetical) A compile-time error occurs if a class or struct overloads operator false without a matching overload for operator &.

The way things are, people are forced (by the C# spec) to write operator false members that have absolutely no chance of ever being invoked.

The question: What is the motivation or historical reason for requiring operator true and operator false to go together?

Community
  • 1
  • 1
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • @Habib Did the requirement _The `true` and `false` unary operators require pair-wise declaration_ make sense back in the old C# 1 days, in your opinion? I do not think it made more sense then. But I do agree that people do not use this a lot because of nullables, but it is still funny (to me) that we have this restriction. – Jeppe Stig Nielsen Dec 18 '14 at 16:18

1 Answers1

0

This is done to force programmers to choose the appropriate tool for the job. If you think that you are overloading operator false with absolutely no chance of ever being invoked, chances are that you should be overloading the conversion operator bool(T) instead.

Operators true and false are there for the most part to cover situations when true and false states are overlapping, i.e. an object can be true and false at the same time (alternatively, it could be neither true nor false).

The situation that you describe, i.e. when only operator true(T) needs to be overloaded, without a matching operator false(T), is covered by a different mechanism - a conversion operator to bool. If all you need is to cover scenario (1) from your question, you override operator bool(T), and use your class in statements that require a bool without having to do anything else.

There is a special case when you must overload operator true and operator false - namely, when you (1) have overloaded operator & or operator |, and (2) you want to use your overloaded operator in a short-circuiting expression. Note that both (1) and (2) are required: when you do not overload operator | or operator &, a single operator bool(T) is sufficient for short-circuiting; same goes for situations when you do not use your operator | or operator & in short-circuiting context.

In this situation language designers have several choices, none of which looks particularly clean, because some constructs that are correct individually become an error when they are used in a combination.

  1. Detect that true and false are overloaded together
  2. Detect that &, which is used for short-circuiting, is overloaded without false
  3. Detect that |, which is used for short-circuiting, is overloaded without true
  4. Detect that true, which is used in short-circuiting context, is overloaded without a matching &
  5. Detect that false, which is used in short-circuiting context, is overloaded without a matching |

The worst part about errors 2 through 5 is that one component of what makes it an error comes from the code that uses your class, not from the code of your class itself.

The compiler designers chose to implement options 1, 2, and 3 (except for 2 and 3 they require both true and false to be overloaded to satisfy 1). They could have picked options 4 and 5 instead, but it wouldn't make it much cleaner, because three different conditions, one of which is beyond your control, would need to be checked anyway.

In the end, they went for the symmetry, making an implicit assumption that if you overload true and false for use in short-circuiting contexts of &, you might as well support the |, and vice versa.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The only use for `operator false` is to signal that we can short-circuit in a `&&` evaluation so that we will not need to invoke the user-defined `operator &`. – Jeppe Stig Nielsen Dec 18 '14 at 16:52