Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

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 :

  1. Why does this in false operator for 1 executes ? I don't see any reason for false to be present here.

  2. 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"

like image 636
Royi Namir Avatar asked Aug 14 '15 11:08

Royi Namir


1 Answers

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.

like image 138
Jon Skeet Avatar answered Sep 29 '22 02:09

Jon Skeet