I have just seen code that used if(!(a == b)) instead of the more commonly seen if(a != b) in C#. I am wondering if there is a difference between the two in C#?
In most cases, they're the same - but they don't have to be. != and == can be overloaded separately, with different logic. Here's an example:
using System;
class Test
{
// All this code is awful. PURELY FOR DEMONSTRATION PURPOSES.
public static bool operator==(Test lhs, Test rhs) => true;
public static bool operator!=(Test lhs, Test rhs) => true;
public override bool Equals(object other) => true;
public override int GetHashCode() => 0;
static void Main()
{
Test a = null;
Test b = null;
Console.WriteLine(a != b); // True
Console.WriteLine(!(a == b)); // False
}
}
In the vast majority of cases, a != b and !(a == b) will have exactly the same behavior, and a != b is almost always clearer. But it's worth being aware that they can differ.
It can get even more pathological - a != b and !(a == b) may even have different types. For example:
using System;
class Test
{
// All this code is awful. PURELY FOR DEMONSTRATION PURPOSES.
public static Test operator==(Test lhs, Test rhs) => new Test();
public static Test operator!=(Test lhs, Test rhs) => new Test();
public static string operator!(Test lhs) => "Negated";
public override string ToString() => "Not negated";
public override bool Equals(object other) => true;
public override int GetHashCode() => 0;
static void Main()
{
Test a = null;
Test b = null;
Console.WriteLine(a != b); // "Not negated"
Console.WriteLine(!(a == b)); // "Negated"
}
}
Here a != b is of type Test, but !(a == b) is of type string. Yes, this is horrible and you're unlikely to run into it in real life - but it's the kind of thing a C# compiler needs to know about.
Sure there's a difference. If ! and == and != are overloaded, then the first calls the first two operators, and the second calls the third. Those are permitted to do very different things, though it would be foolish to do so.
In fact it is common to implement overloaded == and != operators in terms of each other; you might say bool operator !=(C x, C y) => !(x == y); for example. In that case, x != y would be an infinite recursion, which is plainly different than calling !(x == y)!
Logically and conceptually there's no difference, but, since the operators can be overloaded, implementationally there may be a difference.
This highlights a general point in coding though, that any method, operator, property, whatever, should aim to do exactly "what it says on the tin". There should ideally be no surprises, no inconsistent or unexpected behaviour hidden in the implementation.
Related
I have a struct similar to this:
public struct Test
{
public int x;
public int y;
public static bool AreEqual(Test lhs, Test rhs)
{
Contract.Ensures(Contract.Result<bool>() == ((lhs.x == rhs.x) && (lhs.y == rhs.y)));
return (lhs.x == rhs.x) && (lhs.y == rhs.y);
}
public static bool AreNotEqual(Test lhs, Test rhs)
{
Contract.Ensures(Contract.Result<bool>() == !((lhs.x == rhs.x) && (lhs.y == rhs.y)));
return !AreEqual(lhs, rhs);
}
}
It has no problem proving the Ensures for AreEqual, but it can't prove the one for AreNotEqual.
If the Ensures conditions are changed from the form A == B to !A || B and !B || A, which is logically equivalent, it has no problem, but that's far more verbose and less readable.
Likewise, if I just put the equality logic in instead of !AreEqual(lhs, rhs), it's ok, but again, that's repetition I'd rather not have to put in.
My question is: Why can't the CodeContracts static analyser cope with a simple negation? Is there something subtle I'm missing that means it actually can't be inferred?
As a bonus question: Is there documentation anywhere of what the analyser actually does/can do? It seems quite capable sometimes, then fails at something seemingly simple like this example. It'd be nice to know what its "thought process" is when trying to prove these things.
I am unaware of documentation that would answer the bonus question. I also cannot specifically answer why it can't prove the postconditions as written, but if your end goal is simply to reduce duplication of the equality logic, this might help.
The methods result in no visible state changes, and can therefore be marked with the [Pure] attribute. At that point, the .Ensures in AreNotEqual can refer to AreEqual directly. The static analyzer then has enough information, and you only have equality logic expressed in AreEqual.
public struct Test
{
public int x;
public int y;
[Pure]
public static bool AreEqual(Test lhs, Test rhs)
{
Contract.Ensures(Contract.Result<bool>() == ((lhs.x == rhs.x) && (lhs.y == rhs.y)));
return (lhs.x == rhs.x) && (lhs.y == rhs.y);
}
[Pure]
public static bool AreNotEqual(Test lhs, Test rhs)
{
Contract.Ensures(Contract.Result<bool>() == !AreEqual(lhs, rhs));
return !AreEqual(lhs, rhs);
}
}
// CodeContracts: Checked 4 assertions: 4 correct
I've implemented the iEquatable interface:
LineItem : IEquatable<LineItem>
But now I want to debug my Equals(...) method by stepping through the code. But even in debug mode, stepping in doesn't go into it (i.e. F11), and putting a breakpoint inside the method doesn't get me into it either. How can I debug it??
Not that it should be relevant but here is my Equals method:
public bool Equals(LineItem other)
{
List<bool> individuals = new List<bool>();
individuals.Add(DateTime.Equals(Expiry, other.Expiry));
individuals.Add(Code == other.Code);
individuals.Add(Type == other.Type);
individuals.Add(Class == other.Class);
Func<object, object, bool> Compare = delegate(object A, object B)
{
if (A == DBNull.Value || B == DBNull.Value)
return A == B;
else
return (double)A == (double)B;
};
individuals.Add(Compare(Strike, other.Strike));
individuals.Add(Compare(Future, other.Future));
individuals.Add(Compare(Premium, other.Premium));
individuals.Add(Compare(Volatility, other.Volatility));
individuals.Add(Compare(Volume, other.Volume));
individuals.Add(Compare(OpenInterest, other.OpenInterest));
individuals.Add(Compare(Delta, other.Delta));
return !individuals.Contains(false);
}
EDIT:
I'm calling the method from elsewhere in my code like this now:
if(!fo.Future.Equals(li))...
but that still doesn't let me debug it.
You need to take a big step back and learn how to implement equality methods correctly in the first place. C# was designed to be a "pit of success" language; that is, you should naturally "fall into" doing things the right way. Unfortunately, equality is not a "pit of success" in C#; the language designers failed to make it easy to do it right the first time.
Here's the pattern that I use when I override equality.
First, start by writing a private static method that does everything right. Everything else will use this method. Start your method by dealing with (1) the reference equality early out, and (2) null checks.
private static MyEquality(Foo x, Foo y)
{
if (ReferenceEquals(x, y)) return true;
// We now know that they are not BOTH null. If one is null
// and the other isn't then they are not equal.
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
// Now we know that they are both non-null and not reference equal.
... check for value equality here ...
}
OK, now that we have that, we can use that to implement everything else.
public override bool Equals(object y)
{
return MyEquality(this, y as Foo);
}
public override int GetHashcode()
{
// Implement GetHashcode to follow the Prime Directive Of GetHashcode:
// Thou shalt implement GetHashcode such that if x.Equals(y) is true then
// x.GetHashcode() == y.GetHashcode() is always also true.
}
public bool Equals(Foo y)
{
return MyEquality(this, y);
}
That is what is necessary to correctly implement IEquatable<T>.Equals. You should also consider overriding the == operator to be consistent:
public static bool operator ==(Foo x, Foo y)
{
return MyEquality(x, y);
}
public static bool operator !=(Foo x, Foo y)
{
return !MyEquality(x, y);
}
Now no matter whether you call object.Equals(foo, bar), foo.Equals(bar), or foo == bar, you have consistent behavior.
LineItem.Equals(a, b) is a static method call to Object.Equals(object, object); it isn't your method.
This implementation will call a.Equals(object) if you've overridden it, but you did not override it.
What is the workaround to this problem?
class Program
{
static void Main(string[] args)
{
var a = new Test();
var b = new Test();
var eq = Check(a, b);
}
private static bool Check<T>(T a, T b) where T : class
{
return a == b; //will not call overloaded ==
}
}
public class Test
{
public override bool Equals(object obj)
{
Test other = obj as Test;
if (ReferenceEquals(other, null)) return false;
return true;
}
public static bool operator ==(Test left, Test right)
{
return Equals(left, right);
}
public static bool operator !=(Test left, Test right)
{
return !(left == right);
}
}
The == operator is not used because your generic method exists independently of the types you will use for T. It has no way of knowing that all types used as T will overload the == operator... You can use the Equals method instead:
private static bool Check<T>(T a, T b) where T : class
{
return Equals(a, b);
}
The 'solution' here is to call
private static bool Check<T>(T a, T b) where T : class
{
//return a == b; // will not call overloaded ==
return a.Equals(b); // will cal overloaded Equals
}
It's a known behavior. MSDN says:
When applying the where T : class constraint, it is recommended that
you do not use the == and != operators on the type parameter because
these operators will test for reference identity only, not for value equality. This is the case even if these operators are overloaded in
a type used as an argument.
To check equality you have to implement IEqualityComparer (or directly call one of the Equal methods).
The workaround is to call the virtual Equals method, and override that:
private static bool Check<T>(T a, T b) where T : class
{
return a.Equals(b);
}
The overloaded == operator is resolved at compile time, so it is resolved to the System.Object implementation of the operator. A virtual method call is dispatched at run time, so the override of System.Object.Equals (if any) will get called.
In your code, the virtual Equals call is occurring in the overloaded == method, which is not called; that's why the Equals override is not called.
Another solution, if you have control of the classes being passed to the method, would be to constrain to IEquatable<T>, and implement that in your classes:
private static bool Check<T>(T a, T b) where T : class, IEquatable<T>
{
return a.Equals(b);
}
That will cause the overload to resolve to the Equals(T) method, which will save some type checking at run time.
This may well be well-known and discussed, but to my surprise I discovered today that you can give your own implementation of operators between nullables and their base types.
This means that you can have a struct which can be checked for null, and return true.
Now this would be convenient in my situation - on the advice of another member I have a struct that wraps strings. Being able to directly compare this wrapped string directly to null (rather than use a .IsNull or similar) is to me a lot more natural, and means changing from using strings to these WrappedStrings often require no other changes to the code.
But.. the fact that this feature is (I believe) little known, counter-intuitive to anyone thinking struct (which it is) over string (which it represents), and the fact that it confuses ReSharper (structValue == null warns "expression is always false") makes me think this is perhaps a dirty trick left in the dirty but neat tricks cupboard.
So I'm wondering, would you adopt it? If not, would you forgive me for doing so.. or is it really best not to go down this path?
public struct StringWrapper
{
private readonly string str;
public override string ToString() { return str; }
public static bool operator ==(StringWrapper a, StringWrapper b)
{ return a.str == b.str; }
public static bool operator !=(StringWrapper a, StringWrapper b)
{ return !(a == b); }
public static bool operator ==(StringWrapper a, StringWrapper? b)
{
if (!b.HasValue || b.Value.str == null) return a.str == null;
return a == (StringWrapper)b;
}
public static bool operator !=(StringWrapper a, StringWrapper? b)
{ return !(a == b); }
public static bool operator ==(StringWrapper? a, StringWrapper b)
{ return b == a; }
public static bool operator !=(StringWrapper? a, StringWrapper b)
{ return !(a == b); }
public StringWrapper(string str) { this.str = str; }
}
I strongly believe in code that is self-documenting, and goes with the principle of least astonishment. For example, "getters" shouldn't modify data, etc. I would consider comparing a struct variable to null fairly confusing at first glance, so I would avoid it (no matter how convenient it might seem). This would be especially true if you were expecting many people to use (or at least look at) your code.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I check for nulls in an ‘==’ operator overload without infinite recursion?
There is probably an easy answer to this...but it seems to be eluding me. Here is a simplified example:
public class Person
{
public string SocialSecurityNumber;
public string FirstName;
public string LastName;
}
Let's say that for this particular application, it is valid to say that if the social security numbers match, and both names match, then we are referring to the same "person".
public override bool Equals(object Obj)
{
Person other = (Person)Obj;
return (this.SocialSecurityNumber == other.SocialSecurityNumber &&
this.FirstName == other.FirstName &&
this.LastName == other.LastName);
}
To keep things consistent, we override the == and != operators, too, for the developers on the team who don't use the .Equals method.
public static bool operator !=(Person person1, Person person2)
{
return ! person1.Equals(person2);
}
public static bool operator ==(Person person1, Person person2)
{
return person1.Equals(person2);
}
Fine and dandy, right?
However, what happens when a Person object is null?
You can't write:
if (person == null)
{
//fail!
}
Since this will cause the == operator override to run, and the code will fail on the:
person.Equals()
method call, since you can't call a method on a null instance.
On the other hand, you can't explicitly check for this condition inside the == override, since it would cause an infinite recursion (and a Stack Overflow [dot com])
public static bool operator ==(Person person1, Person person2)
{
if (person1 == null)
{
//any code here never gets executed! We first die a slow painful death.
}
return person1.Equals(person2);
}
So, how do you override the == and != operators for value equality and still account for null objects?
I hope that the answer is not painfully simple. :-)
Use object.ReferenceEquals(person1, null) or the new is operator instead of the == operator:
public static bool operator ==(Person person1, Person person2)
{
if (person1 is null)
{
return person2 is null;
}
return person1.Equals(person2);
}
I've always done it this way (for the == and != operators) and I reuse this code for every object I create:
public static bool operator ==(Person lhs, Person rhs)
{
// If left hand side is null...
if (System.Object.ReferenceEquals(lhs, null))
{
// ...and right hand side is null...
if (System.Object.ReferenceEquals(rhs, null))
{
//...both are null and are Equal.
return true;
}
// ...right hand side is not null, therefore not Equal.
return false;
}
// Return true if the fields match:
return lhs.Equals(rhs);
}
"!=" then goes like this:
public static bool operator !=(Person lhs, Person rhs)
{
return !(lhs == rhs);
}
Edit
I modified the == operator function to match Microsoft's suggested implementation here.
you could alway override and put
(Object)(person1)==null
I'd imagine this would work, not sure though.
Easier than any of those approaches would be to just use
public static bool operator ==(Person person1, Person person2)
{
EqualityComparer<Person>.Default.Equals(person1, person2)
}
This has the same null equality semantics as the approaches that everyone else is proposing, but it's the framework's problem to figure out the details :)
The final (hypothetical) routine is below. It is very similar to #cdhowie's first accepted response.
public static bool operator ==(Person person1, Person person2)
{
if (Person.ReferenceEquals(person1, person2)) return true;
if (Person.ReferenceEquals(person1, null)) return false; //*
return person1.Equals(person2);
}
Thanks for the great responses!
//* - .Equals() performs the null check on person2
Cast the Person instance to object:
public static bool operator ==(Person person1, Person person2)
{
if ((object)person1 == (object)person2) return true;
if ((object)person1 == null) return false;
if ((object)person2 == null) return false;
return person1.Equals(person2);
}
Cast the Person to an Object and then perform the comparison:
object o1 = (object)person1;
object o2 = (object)person2;
if(o1==o2) //compare instances.
return true;
if (o1 == null || o2 == null) //compare to null.
return false;
//continue with Person logic.
Overloading these operators consistently is pretty hard. My answer to a related question may serve as a template.
Basically, you first need to do a reference (object.ReferenceEquals) test to see if the object is null. Then you call Equals.
cdhowie is on the money with the use of ReferenceEquals, but it's worth noting that you can still get an exception if someone passes null directly to Equals. Also, if you are going to override Equals it's almost always worth implementing IEquatable<T> so I would instead have.
public class Person : IEquatable<Person>
{
/* more stuff elided */
public bool Equals(Person other)
{
return !ReferenceEquals(other, null) &&
SocialSecurityNumber == other.SocialSecurityNumber &&
FirstName == other.FirstName &&
LastName == other.LastName;
}
public override bool Equals(object obj)
{
return Equals(obj as Person);
}
public static bool operator !=(Person person1, Person person2)
{
return !(person1 == person2);
}
public static bool operator ==(Person person1, Person person2)
{
return ReferenceEquals(person1, person2)
|| (!ReferenceEquals(person1, null) && person1.Equals(person2));
}
}
And of course, you should never override Equals and not override GetHashCode()
public override int GetHashCode()
{
//I'm going to assume that different
//people with the same SocialSecurityNumber are extremely rare,
//as optimise by hashing on that alone. If this isn't the case, change this
return SocialSecurityNumber.GetHashCode();
}
It's also worth noting that identity entails equality (that is, for any valid concept of "equality" something is always equal to itself). Since equality tests can be expensive and occur in loops, and since comparing something with itself tends to be quite common in real code (esp. if objects are passed around in several places), it can be worth adding as a shortcut:
public bool Equals(Person other)
{
return !ReferenceEquals(other, null) &&
ReferenceEquals(this, other) ||
(
SocialSecurityNumber == other.SocialSecurityNumber &&
FirstName == other.FirstName &&
LastName == other.LastName
);
}
Just how much of a benefit short-cutting on ReferenceEquals(this, other) is can vary considerably depending on the nature of the class, but whether it is worth while doing or not is something one should always consider, so I include the technique here.