why can I overload the != operator??

  • Thread starter Thread starter Chris
  • Start date Start date
C

Chris

To me, this seems rather redundant. The compiler requires that if you
overload the == operator, you must also overload the != operator. All I do
for the != operator is something like this:

public static bool operator !=(MyType x, MyType y)
{
return !(x == y);
}

That way the == operator handles everything, and extra comparing logic isn't
needed. I think the C# compiler should NOT allow overloading of the !=
operator, and instead just emit the code I just showed.

I could be completely off my rocker, but this has puzzled me for some time
now, and I just had to ask if someone knows the purpose of allowing the !=
operator to be overloaded.

Chris
 
I guess one of the reasons might be that a more efficient implementation of
the != operator is possible than just negating the outcome of the equality
operator.
 
I guess one of the reasons might be that a more efficient implementation
of
the != operator is possible than just negating the outcome of the equality
operator.

I suppose you're right. In many situations it is easier to determine if
it's not equal than if it is. I do think that it should at least be
optional though. And if it isn't overloaded then the compiler just emits
what I mentioned earlier.

Chris
 
Chris --

I've wondered the same thing many times. As Dmitriy suggests, one
possibility is that there's a more efficient implementation for != (although
it would be interesting to come up with an example). That said, you'd think
the compiler would simply provide an implementation is you don't specify
one. The same goies for (<, >=) and (>, <=).

The other thing that bothers me is that, if you define:

static public bool operator ==(MyType x, MyOtherType o)
{
// Your implementation here
}

you also have to define

static public bool operator ==(MyOtherType o, MyType x)
{
return (x == o);
}

Since equality should always be symmetric, the order of the argument should
never matter. So, why must I define both operators?

Ken
 
I cannot believe they did it for performance. So why can't I overload +=
or -=, instead I have to overload operator+(T a,T b) which must always
return a copy of the object!

In my opinion the C# compiler should provide the != operator automatically
if == is overloaded.
The same should be true in the reverse case, but for the sake of performance
you could still explicity provide both operators.

The same should be true for < and >= or > and <= or operator==(Y a,X b) and
operator==(X b,Y a) or operator true and operator false.

I hope that microsoft will use this idea because it will highly increase
productivity and stability in some cases.
 
There are some types for which this doesn't hold true. The Sql types, for
example, use three state logic, and by SQL rules, null is neither equal nor
not equal to a specific value.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://weblogs.asp.net/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi cody,

I thing += has nothing to do with performance.

First: you should always return an object form + and - operation in order to
be able to do

a = b + c + d +...+ z;
Second: since apparently you cannot overload = operation it make no sence to
overload += and -= because there is no more logic you could provide in this
overload.

--
Stoitcho Goutsev (100) [C# MVP]


cody said:
I cannot believe they did it for performance. So why can't I overload +=
or -=, instead I have to overload operator+(T a,T b) which must always
return a copy of the object!

In my opinion the C# compiler should provide the != operator automatically
if == is overloaded.
The same should be true in the reverse case, but for the sake of performance
you could still explicity provide both operators.

The same should be true for < and >= or > and <= or operator==(Y a,X b) and
operator==(X b,Y a) or operator true and operator false.

I hope that microsoft will use this idea because it will highly increase
productivity and stability in some cases.

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
Chris said:
To me, this seems rather redundant. The compiler requires that if you
overload the == operator, you must also overload the != operator. All I do
for the != operator is something like this:

public static bool operator !=(MyType x, MyType y)
{
return !(x == y);
}

That way the == operator handles everything, and extra comparing logic isn't
needed. I think the C# compiler should NOT allow overloading of the !=
operator, and instead just emit the code I just showed.

I could be completely off my rocker, but this has puzzled me for some time
now, and I just had to ask if someone knows the purpose of allowing the !=
operator to be overloaded.
 
While I can see your point, my issue is that, based on Microsoft's own
recommendations:

1) If you overload "==" you should always overload the Object.Equals()
method.
2) If you overload "==", Object.Equals() and operator == should always
return the same value.

Now, if you override operator != and return something other than the
negation of operator ==, there's no way to do this in an equivalent manner
with Object.Equals (because there's no Object.NotEquals()). That could
certainly lead to confusion and to very bad logic errors if not used
carefully.

Here's Microsoft's remcommendations with regards to operator == and
Object.Equals():

http://msdn.microsoft.com/library/d...nref/html/cpconimplementingequalsoperator.asp

Ken
 
There are some types for which this doesn't hold true. The Sql types, for
example, use three state logic, and by SQL rules, null is neither equal nor
not equal to a specific value.

No. Is SQL every operation where NULL is involved has to return false. That
means that NULL==NULL will also return false. Thats why you have to use
IsNull() for that purpose.
 
I thing += has nothing to do with performance.
First: you should always return an object form + and - operation in order to
be able to do

a = b + c + d +...+ z;
Second: since apparently you cannot overload = operation it make no sence to
overload += and -= because there is no more logic you could provide in this
overload.


So if you think what you're saying here is true think why
System.StringBuilder has no operator+, but System.String has.

in order to implement +=,

string StringBuilder StringBuilder.op_Addition(StringBuilder
sb1,StringBuilder sb2)

would have to be implemented. And this method must return always a new
object in order to work properly. This fact would make the purpose of
StringBuilder very questionable.
 
No. Is SQL every operation where NULL is involved has to return false. That
means that NULL==NULL will also return false. Thats why you have to use
IsNull() for that purpose.

Cody, as usual you completely miss the point.

Oz
 
Hi cody,
So if you think what you're saying here is true think why
System.StringBuilder has no operator+, but System.String has.

in order to implement +=,

string StringBuilder StringBuilder.op_Addition(StringBuilder
sb1,StringBuilder sb2)

would have to be implemented. And this method must return always a new
object in order to work properly. This fact would make the purpose of
StringBuilder very questionable.

I though it would be more polite if I say 'I think...'.
But anyways...

First of all String class doesn't overload + operator either. C# compiler is
the one tha makes you feel like there is such a overload. + operator is
translated as a call to String.Concat method.
Why does c# compiler do that? Because the language designers want C#
programmers to think of the string type as a primitive type. From CLR
perspective it is not. No primive type has overloads of the arithmetic
operators simply because CLR has instructions for that.

The same goes for the 'deciaml' type. But decimal type has +, etc operators
overloaded. The question is 'Why?'

Simply because to have + operator for string types is confusing and kind of
incorrect.

+ is a commutative operation in other words a+b == b+a.
For strings is not. str1 + str2 != str2 + str1
That's why the operation is called concatenation, not addition. And again
because C# designers want porgrammers to tink of string as a primitive type
they decided to provide this operation (and the programmers are kind of use
to it).

On the other hand StringBuilder is not a primitive type and don't have to
have those operatiors.

Second of all you don't have to return a new object from your + operator
overload. For some operators such as -- and ++ it is a must because they
have different behavior when used as prefix and sufix operators. For type
casting operators is obvious because you return objecy of different type.
But for others is up to you.

And finally; don't forget that not all languages support operator overloads
(it is not CLI compliant). In other words is better not to have an overload
for operator than to have only overload without more method with more
descriptive name (e.g. 'Add').
 
So if you think what you're saying here is true think why
I though it would be more polite if I say 'I think...'.
But anyways...

First of all String class doesn't overload + operator either. C# compiler is
the one tha makes you feel like there is such a overload. + operator is
translated as a call to String.Concat method.

I have always been wondering why op_Addition is not documented in the string
class :)
Why does c# compiler do that? Because the language designers want C#
programmers to think of the string type as a primitive type. From CLR
perspective it is not. No primive type has overloads of the arithmetic
operators simply because CLR has instructions for that.
Agreed.

The same goes for the 'decimal' type. But decimal type has +, etc operators
overloaded. The question is 'Why?'

Simply because to have + operator for string types is confusing and kind of
incorrect.

+ is a commutative operation in other words a+b == b+a.
For strings is not. str1 + str2 != str2 + str1
That's why the operation is called concatenation, not addition. And again
because C# designers want porgrammers to think of string as a primitive type
they decided to provide this operation

No, you can have an overload of operator+(X a, Y b) AND operator+(Y a, X b).
That implies that you can implement an operator + which isn't commutative.
On the other hand StringBuilder is not a primitive type and don't have to
have those operatiors.

string isn't either. event and delgate also aren't primitives but support
operator+=.
Second of all you don't have to return a new object from your + operator
overload.

operator+ would not work correctly if you wouldn't return a new object.
And finally; don't forget that not all languages support operator overloads
(it is not CLI compliant). In other words is better not to have an overload
for operator than to have only overload without more method with more
descriptive name (e.g. 'Add').

Agreed but for numeric types or matrices operator overloading makes the code
much more readable.
 
cody,
No, you can have an overload of operator+(X a, Y b) AND operator+(Y a, X b).
That implies that you can implement an operator + which isn't commutative.

No, the purpose of this is to ensure commutativity rather than to make the
operation non-commutative.
Imagine that you declare your own type that make sense to be able to add to
an integer value.

In order to be able to write
MyType + Int and Int + MyType
you have to have both overloads. But I (I believe most of the programmers)
would expect that

MyType + Int == Int + MyType


In my everyday life I use + and * as commutative oprations and - and / as
non commutative. Even though I know that for sime types as matrix for
example * is not. That's the reason why even though Matrix class has
Multiply operation it doesn't provide * operator overload.
string isn't either. event and delgate also aren't primitives but support
operator+=.

Again, string and delegate are not primitive types, but the C# designers
decided that it would be better if the programmers thing of them as such.
Neither String nor delegates classes overloads + (+=) operation. For strings
it is translated to String.Concat; for delegates it is triansated to
MulticastDelegate.Combine
These types are so often used that C# has keywords for them. How often one
uses StringBuilder...
operator+ would not work correctly if you wouldn't return a new object.

I said you don't have to return a new object. You can return the same, but
it will have side effects ofcourse :).

I agree that there are cases (and not only one or two) where overloading X=
operators is useful. Anyways, because of the nature of the binary operators
where side effects are not desired (in other words is better to return new
object ) it is not a big deal that they cannot be overridden explicitly.
Agreed but for numeric types or matrices operator overloading makes the code
much more readable.

That's right. And C# programmers will benefit of that. For VB.NET
programmers let's say it worths nothing.

String and StringBuilder are neither numeric nor metric types so, I don't
see why you so badly want to override them.
 
+ is a commutative operation in other words a+b == b+a.
commutative.

No, the purpose of this is to ensure commutativity rather than to make the
operation non-commutative.
Imagine that you declare your own type that make sense to be able to add to
an integer value.

In order to be able to write
MyType + Int and Int + MyType
you have to have both overloads. But I (I believe most of the programmers)
would expect that

MyType + Int == Int + MyType

I still don't get it. If you only have "operator+(X a, Y b)",
you could theoretically do X+Y or Y+X. The compiler should be able to
substitute
the arguments at its will since commutativity should be assumed for
operator+.
I said you don't have to return a new object. You can return the same, but
it will have side effects ofcourse :)

operator+ cannot work if your don't return a new object. Imagine if
operator+
would simply do "this.val+=x; return val;" then "b = 5+5;" would make 15.
But who cares, value types cannot return references to itself anyway :)
String and StringBuilder are neither numeric nor metric types so, I don't
see why you so badly want to override them.

Not anymore. I now understand why it does not makes sense to overload += and
why it make sense to overload == and != separately.
 
cody,
I still don't get it. If you only have "operator+(X a, Y b)",
you could theoretically do X+Y or Y+X. The compiler should be able to
substitute
the arguments at its will since commutativity should be assumed for
operator+.

No, it won't substitute anything. It will simply say that it can't find the
overload. Overloading operator is not different than overloading methods.
Nobody wants compiler to be so smart to find the order of the parameters by
itself.

operator+ cannot work if your don't return a new object. Imagine if
operator+
would simply do "this.val+=x; return val;" then "b = 5+5;" would make 15.
But who cares, value types cannot return references to itself anyway :)

No, as a result it will be correct. The side effect will be that in the case
of b = 5 + 5 the parameter which operator + is called and the result will be
the same.

You cannot overload + operator for *int* because you cannot inherit from
value type, but to demostrate the this here is some code.

using System;

namespace ConsoleApplication
{

class Foo
{
public int A;

public Foo (int a)
{
A = a;
}

public static Foo operator+(Foo a, int b)
{
a.A += b;

return a;
}

public static Foo operator+(int b, Foo a)
{

return a + b;
}

}



class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{

Foo f = new Foo(5);

Foo f1 = 5 + f;

Console.WriteLine("f1 = 5 + f");
Console.WriteLine("f = {0}", f.A); //f will be 10, which is the
sideeffect
Console.WriteLine("f1 = {0}", f.A);

f = new Foo(5);

f = f + 5;
Console.WriteLine("f = f + 5");
Console.WriteLine("f = {0}", f.A);

f = new Foo(5);

f += 5;
Console.WriteLine("f += 5");
Console.WriteLine("f = {0}", f.A);
}
}
}
 
I still don't get it. If you only have "operator+(X a, Y b)",
No, it won't substitute anything. It will simply say that it can't find the
overload. Overloading operator is not different than overloading methods.
Nobody wants compiler to be so smart to find the order of the parameters by
itself.


But operator is by definition commutative so is there any reason the care
about the order of arguments?
You should always assume that there are no sideeffects with operator
overloading.

No, as a result it will be correct. The side effect will be that in the case
of b = 5 + 5 the parameter which operator + is called and the result will be
the same.

You're right "b = 5+5" works as expected. Your luck :)
But

f = new Foo(5);
f1 = 1 + f + f;

will return 12, not 11. If that is correct I don't know..
If operators have sideeffects they won't work correctly.
 
cody,
But operator is by definition commutative so is there any reason the care
about the order of arguments?
You should always assume that there are no sideeffects with operator
overloading.

See it is not always that you give the operators their mathematical meaning.
For example: String class there is nothing mathematical there; it is a
shorthand for concatenation. In c++ shift operators are used to work with
streams there is nothing mathematical there. So even though oparation +
might be commutative in most of the casses the oparator + might not be. But
again one should be very carefull when choose to change the common meaning
of operators.

f1 = 1 + f + f;

Yes, it returns 12 isntead of 11 and it is incorrect. But in some casses it
might be the desired effect.

This is the flexibility the language gives you. But it has to be used
sparingly, because it maight cause problems than usefulness.
 

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

Back
Top