C# language specs bug with section 7.11.2 ?

G

GP

It appears to be a flaw in the specs, or I did not understand how it works.

7.11.2 User-defined conditional logical operators says that in order to
overload conditional logical operators && and || (which cannot be directly
overloaded in C#) you need to overload the true and false operators and the
compiler will convert expressions like (x && x) to T.op_False(x) ? x :
T.op_BitwiseAnd(x, y). However this results in evaluating the wrong logical
expression since

1 && 2 == op_False(1) ? 1 : op_BitwiseAnd(1, 2) == 0

Now, if I change the op_BitwiseAnd() operator to work as a op_LogicalAnd
then I'm breaking the bitwise And. Also having a bitwise operator acting
like a logical operator seems kind of a bad inconsistency in the language
specs.

Is there something I did not understand, or is there a fix planned for this?

--Gianluca
 
M

Mickey Williams

Wow - a real C# language question.
You're misreading the spec and mixing scalar and logical operations.

&& and & are the logical and operators.
&& short-circuits, & does not.
For scalar types, applying & to two instances performs a bitwise operation.
This is not the case for other types.
For scalar types, you cannot apply && or similar operators, as it makes no
sense to short-circuit these operations.
 
G

GP

Hi Mickey, if you try to overload the conditional logical operators,
following the specs, you will always get the wrong result either in the
logical ops or the bitwise ops. It still seems to me that there is something
wrong in the specs. The only way to make it work is apply logical And in the
bitwise And operator which appears to be logically wrong.

Look at this code:

DbNumber n1 = new DbNumber(1);
DbNumber n2 = new DbNumber(1);

if (n1 && n2)
{
// never gets here because the compiler generated this:
// op_True( op_False(n1) ? n1 : op_BitwiseAnd(n1, n2))
// and it is wrong!
}

if (n1 || n2)
{
// works ok.
}

DbNumber n3 = n1 & n2; // works ok.
DbNumber n4 = n1 | n2; // works ok.


class DbNumber { // it could be struct, it makes no difference

private int m_value;

public DbNumber(int value) {
this.m_value = value;
}

// bitwise and
public static DbNumber operator &(DbNumber n1, DbNumber n2) {
return new DbNumber(n1.m_value & n2.m_value);
}

// bitwise or
public static DbNumber operator |(DbNumber n1, DbNumber n2) {
return new DbNumber(n1.m_value | n2.m_value);
}

// logical operators
public static bool operator true(DbNumber n) {
return n.m_value!=0;
}
public static bool operator false(DbNumber n) {
return n.m_value==0;
}
}
 
A

Alexander Monakhov

Hello, GP.

I think, bitwise and logical semantics are a bit mixed in spec.

Perhaps, it would be more clear to define "x && y" resolution as
"T.false( x ) : false ? T.true( y )". So overloaded '&' wouldn't take
part in short circuit logic.

This definition is much simpler and it strictcly
seperates intuitive semantics:
'&' and '|' are treated as "bitwise" operators, and
'true' and 'false' overloading is left for logical stuff.

But C# design was done in another away. The reason was, may be, to exploit
customization provided by operator overloading.

Imho, your current code is inconsistent with C# spec intuitive sence,
'cause "true( x & y ) != ( true( x ) & true( y ) )".

Best regards!
 
G

GP

Hi Alexander,

x && y === > T.false(x) ? false : T.true(y)
x || y === > T.true(x) ? true : T.true(y)

Would be the right and logical way of resolving the logical And and logical
Or. I suspect that the reason why they did not allow for the overloading of
op_LogicalAnd (apparently it is possible in manged C++) is not to allow the
developer to break the conditional evaluation of expressions in the logical
comparison.

My code is inconsistent because the specs are inconsistent IMO. I overloaded
the bitwise And as a bitwise And (which I thought was a reasonable thing to
do). In order to make the x && y work with the "mixed" specs you need to
implement the bitwise And as a logical And and therefore break the bitwise
And op. I couldn't find any other way. A logical And/Or is as different from
a bitwise And/Or as a multiplication operator is different from a system
crash. :) A logical And between 1 && 2 returns true (1) while a bitwise And
will return 0 (it's obvious, I know). Therefore the assumption that x && y
can be translated to x & y is wrong, IMHO.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top