How does operator overloading of true and false work? - c#

You can overload operator true and false i looked at examples and found this http://msdn.microsoft.com/en-us/library/aa691312%28v=vs.71%29.aspx
I completely dont understand how they work. I know if i write if(obj) and true returns true then the if is executed. It doesnt matter what false returns. However how does false work? in that doc it is suggected that the && operator uses it. I wrote the code below. I dont know how to get && to compile. || gives me a compile error too. How do i get false to be called? and how do i get the && and || to work?
var ts= new MyTimeSpan();// ts += ts;
if (ts){ Console.WriteLine("Is true"); }
else { Console.WriteLine("not true"); }
//Console.WriteLine(ts && ts ? "Y" : "N");
class MyTimeSpan
{
public static MyTimeSpan operator +(MyTimeSpan t, MyTimeSpan t2) { return new MyTimeSpan(); }
public static bool operator true(MyTimeSpan t) { return true; }
public static bool operator false(MyTimeSpan t) { return false; }
}

The defining property of a short circuiting operator is that it doesn't need to evaluate the right side if the left side already determines the result. For or if the left side is true the result will be true in any case and it's unnecessary to evaluate the right side. For and it's the same except that if the left side is false the result will be false.
You need to overload both | and true to get ||. And & and false to get &&.
a||b corresponds to something like op_true(a)?a:(a|b). So if the true operator returns true it does not need to evaluate the expression of b.
a&&b corresponds to something like op_false(a)?a:(a&b). So if the false operator returns true it does not need to evaluate the expression of b.
Overloading the short circuiting operators is useful when creating a custom boolean type, such as nullable bools(See DBBool)

When overloading the true and false operators they don't just return true and false, they are used to determine if a value of your type is considered to be true or false.
If for example a zero value in your class represents false, then a non-zero value represents true:
public static bool operator true(MyTimeSpan t) { return t.Value != 0; }
public static bool operator false(MyTimeSpan t) { return t.Value == 0; }
As the operators are each others inverse, the compiler doesn't need to use both to determine if a value is true or false. If you write if(obj) the compiler will use the true operator to determine if the value is true.

You will need to override & operator for && and | or ||.
Somthing like this: (Just a dummy code)
public static MyTimeSpan operator &(MyTimeSpan t, MyTimeSpan s) { return t; }
public static MyTimeSpan operator |(MyTimeSpan t, MyTimeSpan s) { return t; }

Related

Using null conditional operator("?.") with "function that returns a bool value"

using System;
public class A{
public bool func(){
return true;
}
public int func2(){
return 10;
}
}
public class HelloWorld
{
public static void Main(string[] args)
{
A a = new A();
if(a?.func()){
Console.WriteLine("true"); // Error
}
if(a?.func2() == 10){
Console.WriteLine("true"); // print: True
}
}
}
Like above case, I want to use null conditional operator with A function that returns a bool value.
But, It throws error only when used with bool returning function.
Can I know why it works like that?
Ironically, It works well with the phrase
if(a?.func() == true){
Console.WriteLine("true"); // print: true
}
Please, note that even if func returns bool
a?.func()
returns nullable bool? (true, false and ... null):
a : a?.func()
------------------------------------------
null : null
not null : a.func() # either true or false
So you can put
// if `a` is `null` then `a?.func() is null`
// since `null != true` the condition true if and only if
// `a` is not null and `a.func()` returns true
if (a?.func() == true)
here .net compares T? and T instances (T is bool in our case). It does it as follow
// First compute the expression
bool? result = a?.func()
// Then .net checks if Value is not null
// and if it is the Value equals to required value
if (result.HasValue && result.Value == true) ...
Another way is to use ?? to map null into true or false
// in case of null - when `a` is null - assume false
if (a?.func() ?? false)
The very same logic with
if (a?.func2() == 10)
here a?.func2() returns nullable int? which you compare as == 10, i.e.
if a is not null and a.func2() returns 10 then...
The if statement requires a boolean expression. That is, whatever is inside your parenthesis must resolve to either true or false. When you use the null-conditional operator it says, "give me the bool result of func() unless a is null, then give me null". So by adding the ?. you change your expression to a bool?. But as we established, the if statement requires a bool. if (null) is invalid which is what you get when a is null.
So why does if (a?.func() == true) work? By adding == true, you are now changing your expression back to a bool result type by doing a comparison. When a is null, instead of being
if (null)
you now have
if (null == true)
which is a valid boolean expression that resolves to false. So incidentally, the inverse is also valid if (a?.func() == false).

Short method to check if integer is 0 and return a boolean

Can this be done in a better way?
public bool AreMoreNeeded() => EntitiesNeededCount == 0 ? true : false;
I am using this to check if an integer is 0 and return a boolean based on the operation result .
yes, remove the true and false:
public bool AreMoreNeeded() => EntitiesNeededCount == 0;
the equality operator :
The equality operator == returns true if its operands are equal, false otherwise.
EDIT:
You can make it even a little more shorter and make it a property instead of a method:
public bool AreMoreNeeded => EntitiesNeededCount == 0;

Conditional operator without return value

I have this code:
bool value = false;
if(value)
{
Console.Write("true");
}
else
{
Console.Write("false");
}
and I want to shorten it by using the conditional operator but I can't find the correct syntax.
bool value = false;
value ? Console.Write("true") : Console.Write("false"); // does not work
Put the operator inside Console.Write
Console.Write(value ? "true" : "false");
or if you really want to write the value:
Console.Write(value);
if you want to call 2 different Methods, you can write your if-statement in one line:
if (value) Method1(); else Method2();
bool value = false;
Console.Write(value ? "true" : "false");
If method returns a value then
bool value = false;
var result = value ? Test1() : Test2();
private int Test1()
{
return 1;
}
private int Test2()
{
return 1;
}
Just adding some precisions to the previous answer. The reason why you can't do this:
value ? Console.Write("true") : Console.Write("false");
Is because:
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression.
source: MSDN
The keyword here is "return". The ternary operator doesn't exactly replace an if/else statement, it is meant for assignment. You can of course call a method within a ternary operation as long as it returns a boolean value. A ternary operator must return something.

&& operator overloading and assignments in C# - Clarification?

Following this very interesting issue which was originated from this question -
I want to take 1 steps back please (removed the dynamic environment) :
Looking at this code : ( a variant of this one)
void Main()
{
int a;
int b = 100;
Console.WriteLine(X.M(1, out a));
}
public class X
{
public int H=0;
public static X M(int x, out int y)
{
Console.WriteLine("x = "+x);
y = x;
return new X(x);
}
public X(){}
public X(int h)
{
H=h;
}
public static bool operator false(X x) {Console.WriteLine("in false operator for "+ x.H); return true; }
public static bool operator true(X x) {Console.WriteLine("in true operator for "+ x.H); return true; }
public static X operator &(X a, X b) {Console.WriteLine("in & operator for "+ a.H+","+b.H); return new X(); }
public static implicit operator bool (X x) {Console.WriteLine("in bool operator for "+ x.H);return true; }
}
The result is :
x = 1
in bool operator for 1
True
This is understood :
The x = 1 is from the method itself ( using Console.Writeline)
in bool operator for 1 is from the implicit operator from X to Bool
(so - Console.WriteLine treats the whole expression as Console.Writeline(bool))
The last "True" is from the "return true" in the operator bool (X x)
OK - So let's change
Console.WriteLine(X.M(1, out a));
to
Console.WriteLine(X.M(1, out a) && X.M(2, out b));
Now - the result is :
x = 1
in false operator for 1
in bool operator for 1
True
2 questions :
Why does this in false operator for 1 executes ? I don't see any reason for false to be present here.
I could understand why the right part in X.M(1, out a) && X.M(2, out b) won't executes ONLY if the left part is false - but again I don't see how the left part can be false. It does return true (according to my first code)
NB
I've read many times the answers from the post :
Jon said :
The second && is a normal && between two bool expressions - because
Nop returns bool, and there's no &(X, bool) operator... but there is a
conversion from X to bool.
So it's more like:
bool first = X.M(1, out a) && X.M(2, out b);
if (first && Nop(a, b))
Now first is true even though only the first operand of && has been
evaluated... so b really hasn't been assigned.
Still I don't understand : "first is true(????) even though only the first operand of && has been evaluated"
Firstly, don't forget that this is deliberately bizarre code, used to find a corner case. If you ever find a type that behaves like this in a genuine program, find the author and have a quiet word with them.
Still I don't understand : "first is true(????) even though only the first operand of && has been evaluated"
Yes, because of the way the && operand is handled in the case where the operands aren't bool. It's specified in section 7.12.2 of the C# spec:
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 &. 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.
So, in order:
X.M(1, out a) is invoked, to get a result - call it op1 for the moment
Next X.false(op1) is invoked, and returns true
Then by the above, the result of the expression X.M(1, out a) && X.M(2, out b) is op1
Next, the value of the conversion from op1 to bool is invoked, and that returns true. This is due to overload resolution for Console.WriteLine.
To answer your specific confusion:
but again I don't see how the left part can be false.It does return true (according to my first code)
It returns a value which is somewhat contradictory - it's false in that the false operator returns true, but it's true in that the conversion to bool returns true. Once you understand that it's the value returned by the false operator which determines whether or not to evaluate the second operand of &&, it should all be clear.

When does overloaded false operator ever gets executed and what is it good for?

I've been searching for actual working code where an overloaded false operator actually gets executed.
This question (What's the false operator in C# good for?) is somewhat the same, but the accepted answer links to an url which is returning a 404 error. I've also looked at How does operator overloading of true and false work? and some other questions.
What I've found in almost all answers is that false only gets executed when you use a short circuited and like x && y. This is evaluated as T.false(x) ? x : T.&(x, y).
Ok, so I have the following code. The struct contains an int and considers itself true if the int is greater than zero.:
public struct MyStruct {
private int _i;
public MyStruct(int i) {
_i = i;
}
public static bool operator true(MyStruct ms) {
return ms._i > 0;
}
public static bool operator false(MyStruct ms) {
return ms._i <= 0;
}
public override string ToString() {
return this._i.ToString();
}
}
Now I would hope the following program will execute and use the overloaded false operator.
class Program {
private static void Main() {
MyStruct b1 = new MyStruct(1); // to be considered true
MyStruct b2 = new MyStruct(-1); // to be considered false
Console.WriteLine(b1 && b2);
Console.WriteLine(b2 && b1);
}
}
However, it does not even compile. It says it cannot apply operator '&&' to operands of type 'MyStruct' and 'MyStruct'.
I know I can implement an overload of the & operator. So let's do that. The & must return a MyStruct, so I can not make it return a bool.
public static MyStruct operator &(MyStruct lhs, MyStruct rhs) {
return new MyStruct(lhs._i & rhs._i);
}
Now the code does compile. Its output is 1 and -1. So the result of b1 && b2 is not the same as that of b2 && b1.
If I debug the code, I see that b1 && b2 first executes the false operator on b1, which returns false. Then it performs the & operator on b1 and b2, which performs a bitwise and on 1 and -1, resulting in 1. So it indeed is first checking if b1 is false.
The second expression, b2 && b1 first executes the false operator on b2, which returns true. Combined with the fact I'm using short circuiting, it doesn't do anything with b1 and just prints out the value of b2.
So yes, the false operator is executed when you use short circuiting. However, it does not execute the true or false operator on the second argument, but instead executes the overloaded & operator on the operands.
When can this ever be useful? Or how can I make my type so that it can check if the two variables both are true?
The contents of the URL you mentioned that was 404 can be found here:
http://web.archive.org/web/20080613013350/http://www.ayende.com/Blog/archive/2006/08/04/7381.aspx
The article that the author is referring to is here:
http://web.archive.org/web/20081120013852/http://steve.emxsoftware.com/NET/Overloading+the++and++operators
To avoid the same issue again, here is the highlights from the article:
A couple months ago I posted about our query API along with an explanation of how it works. Our query API allows us to express our queries using strongly typed C# syntax:
List<Customer> customers = repository.FindAll(Customer.Columns.Age == 20 & Customer.Columns.Name == “foo”);
One of the things I pointed out in my previous posts was that I couldn’t overload the && and || operators directly since the framework doesn’t allow such craziness…at least not directly.
In particular, it is not possible to overload member access, method invocation, or the =, &&, ||, ?:, checked, unchecked, new, typeof, as, and is operators.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfcsharpspec_7_2_2.asp
Over the last month I’ve done a little investigation on the topic to see if and how I can get && and || to behave the way I want. This evening I came across the Conditional logical operators page on MSDN which gave me the answer I was looking for:
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.
The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x, y) is an invocation of the selected operator |. In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. Then, if x is definitely true, 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.
Since we already have the & and | operators in place it was simply a matter of overloading the true and false operators to both return false. This results in the & and | operators always being called which in turn results in the two criteria objects being turned into an AndCriteria/OrCriteria!
So now we can express our criteria expressions using the && and || syntax we’re accustomed to.
repository.FindAll(Customer.Columns.Age == 20 && Customer.Columns.Name == “foo”);
repository.FindAll(Customer.Columns.FirstName == “Foo” || Customer.Columns.LastName == “Bar”);
The relevant operator overloads are shown below.
public static bool operator true(Criteria<T> criteria) {
return false;
}
public static bool operator false(Criteria<T> criteria) {
return false;
}
public static Criteria<T> operator &(Criteria<T> lhs, Criteria<T> rhs) {
return new AndCriteria<T>(lhs, rhs);
}
public static Criteria<T> operator |(Criteria<T> lhs, Criteria<T> rhs) {
return new OrCriteria<T>(lhs, rhs);
}
EDIT-
Reading the linked article I was able to get the following output which uses both the true and false operators:
op false on 1
op & on 1 -1
op true on 1
op true on -1
FALSE
op false on -1
op true on -1
FALSE
op true on 1
op true on 1
TRUE
op true on -1
op & on -1 1
op true on -1
op true on 1
TRUE
With the code:
class Program
{
static void Main(string[] args)
{
MyStruct b1 = new MyStruct(1); // to be considered true
MyStruct b2 = new MyStruct(-1); // to be considered false
Console.WriteLine((b1 && b2) ? "TRUE" : "FALSE");
Console.WriteLine((b2 && b1) ? "TRUE" : "FALSE");
Console.WriteLine((b1 || b2) ? "TRUE" : "FALSE");
Console.WriteLine((b2 || b1) ? "TRUE" : "FALSE");
Console.ReadLine();
}
}
public struct MyStruct
{
private int _i;
public MyStruct(int i)
{
_i = i;
}
public static bool operator true(MyStruct ms)
{
Console.WriteLine("op true on {0}", ms);
return ms._i > 0;
}
public static bool operator false(MyStruct ms)
{
Console.WriteLine("op false on {0}", ms);
return ms._i <= 0;
}
public static MyStruct operator &(MyStruct lhs, MyStruct rhs)
{
Console.WriteLine("op & on {0} {1}", lhs, rhs);
if (lhs)
{
return rhs;
}
else
{
return new MyStruct(-1); //-1 is false
}
}
public static MyStruct operator |(MyStruct lhs, MyStruct rhs)
{
Console.WriteLine("op & on {0} {1}", lhs, rhs);
if (lhs)
{
return lhs;
}
else
{
return rhs;
}
}
public override string ToString()
{
return this._i.ToString();
}
}
I'm not sure what you mean when you say the first code can't compile, although it doesnt use the operator true/false, I ran the following code in 2010 express and got the output:
op bool on 1
op bool on -1
False
op bool on -1
False
op bool on -1
op bool on 1
True
op bool on 1
True
Code:
class Program
{
static void Main(string[] args)
{
MyStruct b1 = new MyStruct(1); // to be considered true
MyStruct b2 = new MyStruct(-1); // to be considered false
Console.WriteLine(b1 && b2);
Console.WriteLine(b2 && b1);
Console.WriteLine(b2 || b1);
Console.WriteLine(b1 || b2);
Console.ReadLine();
}
}
public struct MyStruct
{
private int _i;
public MyStruct(int i)
{
_i = i;
}
public static bool operator true(MyStruct ms)
{
Console.WriteLine("op true on {0}", ms);
return ms._i > 0;
}
public static bool operator false(MyStruct ms)
{
Console.WriteLine("op false on {0}", ms);
return ms._i <= 0;
}
public static implicit operator bool(MyStruct ms)
{
Console.WriteLine("op bool on {0}", ms);
return ms._i > 0;
}
public override string ToString()
{
return this._i.ToString();
}
}
Answering your last question: "how can I make my type so that it can check if the two variables both are true?" - just use the & operator. The whole point of && is to short circuit, so that the second argument isn't checked when not necessary.
Check this out:
Console.WriteLine(b1 & b2); // outputs 1
Console.WriteLine(b2 & b1); // outputs 1
You are actually missing one important bit which will allow you to use MyStruct (with & and |) as a boolean - an implicit cast to bool:
public static implicit operator bool(MyStruct ms) {
return ms._i > 0;
}
This allows you to use MyStruct (so also the result of the operators) as such:
if (b1 & b2)
Console.WriteLine("foo");
As the last, possibly most important, note: the problem in your example comes from the fact that you want to do logical operations (check whether 2 instances of MyStruct are true), but your & operator is implemented incorrectly for such a purpose. It works in terms of binary arithmetic, yielding an instance of MyStruct with value 1 when called with arguments MyStruct(1) (true) and MyStruct(-1) (false). So it basically does (true & false) == true. This is why b1 && b2 gives a different result than b2 && b1 in your example. Any further logic based off of this operator will be broken and unpredictable. Behavior of &&, which is implemented in .NET in terms of false and &, confirms this.
EDIT: you want to be able to use MyStruct as a boolean. You implement operators true and false and expect && and || to work in terms of boolean logic. However, you implement & in terms of binary arithmetics (using & on int fields), which makes this implementation of & not compatible with the boolean logic you expect ((1 & -1) == 1, which means (true & false) == false in your interpretation of MyStruct boolean value). Now, consider that && in general is not a logical operator (it doesn't return a bool) - it is a short circuit implemented as T.false(x) ? x : T.&(x, y). Note that it returns MyStruct in your case, which you just interpret as true or false based on the value of its field. The bottom line: you expect && to do a logical test on both operands, but the .NET implementation of && uses your implementation of &, which is not compatible with the boolean logic you expect.
From Microsoft (http://msdn.microsoft.com/en-us/library/6292hy1k.aspx):
Prior to C# 2.0, the true and false operators were used to create user-defined
nullable value types that were compatible with types such as SqlBool. However,
the language now provides built-in support for nullable value types, and
whenever possible you should use those instead of overloading the true and
false operators.
If you're looking to just evaluate your object to a boolean, remove the operator true and operator false overloads and just use the bool overload.
The point of true/false operators is to provide boolean logic semantics without the need for implicit conversion to bool.
If you allow your type to implicitly cast into bool, the true/false operators are no longer needed. But if you want only explicit conversion, or no conversion, but still want to allow your type as a condition in if or while expresssion, you can use true and false operators.

Categories

Resources