Out of curiosity, I explored overloading operators in C#. There is an interesting post by Eric Lippert discussing the design decisions in C++ and C# concerning operator&&
. In C# its overloads are defined implicitly by overloading operator&
plus overloading the boolean operators true
and false
, which allows the language to preserve the sometimes essential short-circuit semantics.
Playing with the somewhat exotic operator true()
and false()
I found that I was not able to call them directly. Instead, they are implicitly called in certain places where a bool is required. As far as I can see, these are the language constructs which directly require a bool, namely the ternary conditionaly operator and the if clause, plus calls to operator&&
resp. ||
when the argument type has overloaded operators &
resp. |
.
Edit: The book "The C# Programming Language" (7.11) as well as the annotated C# Standard in 14.11.2 -- both found via google search result -- have a code example with a direct operator call which I didn't understand must be pseudo code. I tried to replicate that.
As an aside, it is harder to provoke a call to operator false()
; the ternary conditional as well as an if clause always test by calling operator true()
. It seems as if the only way to call it is by calling operator||()
.
The motivation to call the boolean operators explicitly is that it would be nice to define only one of them directly and define the other one in terms of that, so that the definitions are always consistent. Below is a little example program with a few things I tried. Is there a syntax which I missed?
using System;
namespace TriviallyTrue
{
public class T
{
public static bool operator true(T t) { Console.WriteLine("In op. true"); return true; }
public static bool operator false(T t) { return true; }
}
class Program
{
static void Main(string[] args)
{
T t = new T();
// bool b = T.true(t); // Identifier expected; 'true' is a keyword
// ok, I see. Let's use the keyword syntax.
// bool b = T.@true(t); //'TriviallyTrue.T' does not contain a definition for 'true'
// That's so not true!
// oh. perhaps we need to use cast syntax, akin to invoking operator int()?
// bool b = (true)t; // ; expected
// hm. It's in T's namespace...
// bool b = (T.true)t; // Identifier expected;
// we know that.
// another cast try.
// bool b = (T.@true)t; // The type name 'true' does not exist in the type 'TriviallyTrue.T'
// ah, a type is expected. Well, the type is bool, right? But casting to bool
// doesn't work either, see below and in Main().
// bool b = (T.@bool)t; // The type name 'bool' does not exist in the type 'TriviallyTrue.T'
// well, it exists *some*what
if (t) // works
{
// Console.WriteLine("t was " + (bool)t); // Cannot convert type 'TriviallyTrue.T' to 'bool'
// That's so not true!
Console.WriteLine("t was " + (t ? "True" : "False" )); // works!
}
}
}
}
Sample session:
In op. true
In op. true
t was True