Difference between .Equals(N) and == N [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
== or .Equals()
I have a String Array and just want to count number of splitted string items in the array.
But I can't decide on which version I want/need/should use:
if(myStringArray.Count.Equals(47))
{
// Do something.
}
or
if(myStringArray.Count == 47)
{
// Do something.
}
Could someone please help me understand the difference between the two approaches and why both ones exist?
I've tried both, and both produce the same result.

The Equals method provides a means for an object type to define "equality" between two instances. With numbers, Equals and == are the same thing, but when you're using object types they're different: Equals compares equality (are the two objects equivalent to each other), and == compares identity (are the two references to the same object). The class author will override Equals and (typically) compare either all of the object's fields with the other object's fields or compare key fields, depending on the class.

In the case of a struct, like the integer used here, there won't be a difference. For classes there could be.
For structs as int,bool,datetime, etc, the intrinsic value is compared with == and not the reference.
for classes == compares the reference, but equals can be overridden to apply custom comparisson.
for example, if class Foo is a class that contains a primary key, and has overridden it's base equals implementation to compare the keys:
var foo1 = new Foo{PrimaryKey = 5};
var foo2 = new Foo{PrimaryKey = 5};
foo1 == foo2 //false
foo1.Equals(foo2) //true

Could someone please help me understand the difference between the two approaches
There is no difference in functionality, but the second one is easier to read and understand, so it is preferred.
and why both ones exist?
In C#, System.Int32 is a structure, so it has an Equals(Object) method inherited from System.Object. The .NET developers also added an Equals(Int32) method, which provides an alternative with the same syntax. I have never seen Equals(Int32) used in production code, just because == is easier to read.

Related

C# RequireNonDefaultAttribute strange behaviour: Equals vs == inside IsValid() [duplicate]

This question already has answers here:
C# difference between == and Equals()
(20 answers)
Closed 9 years ago.
What is the difference between a.Equals(b) and a == b for value types, reference types, and strings? It would seem as though a == b works just fine for strings, but I'm trying to be sure to use good coding practices.
From When should I use Equals and when should I use ==:
The Equals method is just a virtual
one defined in System.Object, and
overridden by whichever classes choose
to do so. The == operator is an
operator which can be overloaded by
classes, but which usually has
identity behaviour.
For reference types where == has not
been overloaded, it compares whether
two references refer to the same
object - which is exactly what the
implementation of Equals does in
System.Object.
Value types do not provide an overload
for == by default. However, most of
the value types provided by the
framework provide their own overload.
The default implementation of Equals
for a value type is provided by
ValueType, and uses reflection to make
the comparison, which makes it
significantly slower than a
type-specific implementation normally
would be. This implementation also
calls Equals on pairs of references
within the two values being compared.
using System;
public class Test
{
static void Main()
{
// Create two equal but distinct strings
string a = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
string b = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
Console.WriteLine (a==b);
Console.WriteLine (a.Equals(b));
// Now let's see what happens with the same tests but
// with variables of type object
object c = a;
object d = b;
Console.WriteLine (c==d);
Console.WriteLine (c.Equals(d));
}
}
The result of this short sample program is
True
True
False
True
Here is a great blog post about WHY the implementations are different.
Essentially == is going to be bound at compile time using the types of the variables and .Equals is going to be dynamically bound at runtime.
In the most shorthand answer:
== opertator is to check identity. (i.e: a==b are these two are the same object?)
.Equals() is to check value. (i.e: a.Equals(b) are both holding identical values?)
With one exception:
For string and predefined value types (such as int, float etc..),
the operator == will answer for value and not identity. (same as using .Equals())
One significant difference between them is that == is a static binary operator that works on two instances of a type whereas Equals is an instance method. The reason this matters is that you can do this:
Foo foo = new Foo()
Foo foo2 = null;
foo2 == foo;
But you cannot do this without throwing a NullReferenceException:
Foo foo = new Foo()
Foo foo2 = null;
foo2.Equals(foo);
At a simple level, the difference is which method is called. The == method will attempt ot bind to operator== if defined for the types in question. If no == is found for value types it will do a value comparison and for reference types it will do a reference comparison. A .Equals call will do a virtual dispatch on the .Equals method.
As to what the particular methods do, it's all in the code. Users can define / override these methods and do anything they please. Ideally this methods should be equivalent (sorry for the pun) and have the same output but it is not always the case.
One simple way to help remember the difference is that a.Equals(b) is more analogous to
a == (object)b.
The .Equals() method is not generic and accepts an argument of type "object", and so when comparing to the == operator you have to think about it as if the right-hand operand were cast to object first.
One implication is that a.Equals(b) will nearly always return some value for a and b, regardless of type (the normal way to overload is to just return false if b is an unkown type). a == b will just throw an exception if there's no comparison available for those types.
"==" is an operator that can be overloaded to perform different things based on the types being compared.
The default operation performed by "==" is a.Equals(b);
Here's how you could overload this operator for string types:
public static bool operator == (string str1, string str2)
{
return (str1.Length == str2.Length;)
}
Note that this is different than str1.Equals(str2);
Derived classes can also override and redefine Equals().
As far as "best practices" go, it depends on your intent.
For strings you want to be careful of culture specific comparisons. The classic example is the german double S, that looks a bit like a b. This should match with "ss" but doesn't in a simple == comparison.
For string comparisons that are culture sensitive use: String.Compare(expected, value, StringComparison....) == 0 ? with the StringComparison overload you need.
By default, both == and .Equals() are equivalent apart from the possibility of calling .Equals() on a null instance (which would give you a NullReferenceException). You can, however, override the functionality of either of them independently (though I'm not sure that would ever be a good idea unless you're trying to work around the shortcomings of another system), which would mean you could MAKE them different.
You'll find people on both sides of the aisle as to the one to use. I prefer the operator rather than the function.
If you're talking about strings, though, it's likely a better idea to use string.Compare() instead of either one of those options.

Why does the Equals implementation for anonymous types compare fields?

I'm just wondering why designers of the language decided to implement Equals on anonymous types similarly to Equals on value types. Isn't it misleading?
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public static void ProofThatAnonymousTypesEqualsComparesBackingFields()
{
var personOne = new { Name = "Paweł", Age = 18 };
var personTwo = new { Name = "Paweł", Age = 18 };
Console.WriteLine(personOne == personTwo); // false
Console.WriteLine(personOne.Equals(personTwo)); // true
Console.WriteLine(Object.ReferenceEquals(personOne, personTwo)); // false
var personaOne = new Person { Name = "Paweł", Age = 11 };
var personaTwo = new Person { Name = "Paweł", Age = 11 };
Console.WriteLine(personaOne == personaTwo); // false
Console.WriteLine(personaOne.Equals(personaTwo)); // false
Console.WriteLine(Object.ReferenceEquals(personaOne, personaTwo)); // false
}
At first glance, all printed boolean values should be false. But lines with Equals calls return different values when Person type is used, and anonymous type is used.
Anonymous type instances are immutable data values without behavior or identity. It doesn't make much sense to reference-compare them. In that context I think it is entirely reasonable to generate structural equality comparisons for them.
If you want to switch the comparison behavior to something custom (reference comparison or case-insensitivity) you can use Resharper to convert the anonymous type to a named class. Resharper can also generate equality members.
There is also a very practical reason to do this: Anonymous types are convenient to use as hash keys in LINQ joins and groupings. For that reason they require semantically correct Equals and GetHashCode implementations.
For the why part you should ask the language designers...
But I found this in Eric Lippert’s article about Anonymous Types Unify Within An Assembly, Part Two
An anonymous type gives you a convenient place to store a small
immutable set of name/value pairs, but it gives you more than that. It
also gives you an implementation of Equals, GetHashCode and, most
germane to this discussion, ToString. (*)
Where the why part comes in the note:
(*) We give you Equals and GetHashCode so that you can use instances
of anonymous types in LINQ queries as keys upon which to perform
joins. LINQ to Objects implements joins using a hash table for
performance reasons, and therefore we need correct implementations of
Equals and GetHashCode.
The official answer from the C# Language Specification (obtainable here):
The Equals and GetHashcode methods on anonymous types override the methods inherited from object, and are defined in terms of the Equals and GetHashcode of the properties, so that two instances of the same anonymous type are equal if and only if all their properties are equal.
(My emphasis)
The other answers explain why this is done.
It's worth noting that in VB.Net the implementation is different:
An instance of an anonymous types that has no key properties is equal only to itself.
The key properties must be indicated explicitly when creating an anonymous type object. The default is: no key, which can be very confusing for C# users!
These objects aren't equal in VB, but would be in C#-equivalent code:
Dim prod1 = New With {.Name = "paperclips", .Price = 1.29}
Dim prod2 = New With {.Name = "paperclips", .Price = 1.29}
These objects evaluate to "equal":
Dim prod3 = New With {Key .Name = "paperclips", .Price = 1.29}
Dim prod4 = New With {Key .Name = "paperclips", .Price = 2.00}
Because it gives us something that's useful. Consider the following:
var countSameName = from p in PersonInfoStore
group p.Id by new {p.FirstName, p.SecondName} into grp
select new{grp.Key.FirstName, grp.Key.SecondName, grp.Count()};
The works because the implementation of Equals() and GetHashCode() for anonymous types works on the basis of field-by-field equality.
This means the above will be closer to the same query when run against at PersonInfoStore that isn't linq-to-objects. (Still not the same, it'll match what an XML source will do, but not what most databases' collations would result in).
It means we don't have to define an IEqualityComparer for every call to GroupBy which would make group by really hard with anonymous objects - it's possible but not easy to define an IEqualityComparer for anonymous objects - and far from the most natural meaning.
Above all, it doesn't cause problems with most cases.
The third point is worth examining.
When we define a value type, we naturally want a value-based concept of equality. While we may have a different idea of that value-based equality than the default, such as matching a given field case-insensitively, the default is naturally sensible (if poor in performance and buggy in one case*). (Also, reference equality is meaningless in this case).
When we define a reference type, we may or may not want a value-based concept of equality. The default gives us reference equality, but we can easily change that. If we do change it, we can change it for just Equals and GetHashCode or for them and also ==.
When we define an anonymous type, oh wait, we didn't define it, that's what anonymous means! Most of the scenarios in which we care about reference equality aren't there any more. If we're going to be holding an object around for long enough to later wonder if it's the same as another one, we're probably not dealing with an anonymous object. The cases where we care about value-based equality come up a lot. Very often with Linq (GroupBy as we saw above, but also Distinct, Union, GroupJoin, Intersect, SequenceEqual, ToDictionary and ToLookup) and often with other uses (it's not like we weren't doing the things Linq does for us with enumerables in 2.0 and to some extent before then, anyone coding in 2.0 would have written half the methods in Enumerable themselves).
In all, we gain a lot from the way equality works with anonymous classes.
In the off-chance that someone really wants reference equality, == using reference equality means they still have that, so we don't lose anything. It's the way to go.
*The default implementation of Equals() and GetHashCode() has an optimisation that let's it use a binary match in cases where it's safe to do so. Unfortunately there's a bug that makes it sometimes mis-identify some cases as safe for this faster approach when they aren't (or at least it used to, maybe it was fixed). A common case is if you have a decimal field, in a struct, then it'll consider some instances with equivalent fields as unequal.

Why are two empty Lists not Equal?

I thought calling Equals() on two empty Lists would return true, but that's not the case. Could someone explain why?
var lst = new List<Whatever>();
var lst2 = new List<Whatever>();
if(!lst.Equals(lst2))
throw new Exception("seriously?"); // always thrown
Because Equals is checking for references - lst and lst2 are different objects. (note that Equals is inherited from Object and not implemented in List<T>)
You're looking for Linq's SequenceEquals.
Even when using SequenceEquals, don't expect it to work with your Whatever class on non-empty lists (unless it is a struct). You may want to implement a comparer, and use the right overload.
Equals here is comparing reference of two lists which would be different because they are separate lists and that's why it will always be false in this case.
Object documentation (MSDN documentation):
The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.
List documentation (MSDN documentation):
Determines whether the specified Object is equal to the current Object. (Inherited from Object.)
You have two different objects (two times new ...) so there not the same.
Because it compares on object identity, not the contents of the list. They are two separate objects.
See this answer from the C# FAQ.
The Equals implementation of List<T> is the inherited one from Object:
The default implementation of Equals supports reference equality for reference types
In other words, since these are two different lists, they have different references, so Equals returns false.
List<T>.Equals() will compare the references of the two lists and return true if they are equal. If you want to compare the elements of two lists, use List<T>.SequenceEquals()
When you compare 2 lists with each other, the equals method will NOT compare the items that are in that list. It will just compare the List object with the other List object. these have their own 'identity'.
They are two different lists allocated somewhere in memory (with new keyword). Therefore they cannot be equal. If you want such functionality you should build your own object inheriting from List and overriding Equals function
In C# and .Net you have reference types and value types.
Value types represent, well, values. integer, double, DateTime and so on.
When you compare value types you compare their actual value, so:
int a = 10;
int b = 10;
if( a == b )
{
// this will fire
}
Note that each variable refers to a new copy, so:
int c = a;
c = c+5;
if( a == c )
{
// this won't, because a==10 and c==15
}
Reference types are objects that you pass around a do things with. You can have more than one variable referring to the the same object, so:
var a = new List<Whatever>();
var b = new List<Whatever>();
if( a == b )
{
// this won't fire, a and be are separate objects
}
var c = a;
c.Add(new Whatever());
if( a == c )
{
// this will, a and c are the same object.
a[0]; // holds the value added to c
}
Finally some special cases of reference types behave like value types, for instance string.
As far as I can see from the documentation .Equals on List is the inherited method from Object which means it checks if the lists are the same object. Since you have made two object they will not be the same.
Two different things cant be the same, even if these things got the same items (or are both empty).
You dont need to be good at programing to understand this ;) Lets say you have a this and that, its not important whats inside this and that. Its just important that a this is not a that or a that is not a this. Thats what you you check there with equals

When can a == b be false and a.Equals(b) true?

I ran into this situation today. I have an object which I'm testing for equality; the Create() method returns a subclass implementation of MyObject.
MyObject a = MyObject.Create();
MyObject b = MyObject.Create();
a == b; // is false
a.Equals(b); // is true
Note I have also over-ridden Equals() in the subclass implementation, which does a very basic check to see whether or not the passed-in object is null and is of the subclass's type. If both those conditions are met, the objects are deemed to be equal.
The other slightly odd thing is that my unit test suite does some tests similar to
Assert.AreEqual(MyObject.Create(), MyObject.Create()); // Green bar
and the expected result is observed. Therefore I guess that NUnit uses a.Equals(b) under the covers, rather than a == b as I had assumed.
Side note: I program in a mixture of .NET and Java, so I might be mixing up my expectations/assumptions here. I thought, however, that a == b worked more consistently in .NET than it did in Java where you often have to use equals() to test equality.
UPDATE Here's the implementation of Equals(), as requested:
public override bool Equals(object obj) {
return obj != null && obj is MyObjectSubclass;
}
The key difference between == and Equals is that == (like all operators) is not polymorphic, while Equals (like any virtual function) is.
By default, reference types will get identical results for == and Equals, because they both compare references. It's also certainly possible to code your operator logic and Equals logic entirely differently, though that seems nonsensical to do. The biggest gotcha comes when using the == (or any) operator at a higher level than the desired logic is declared (in other words, referencing the object as a parent class that either doesn't explicitly define the operator or defines it differently than the true class). In such cases the logic for the class that it's referenced as is used for operators, but the logic for Equals comes from whatever class the object actually is.
I want to state emphatically that, based solely upon the information in your question, there is absolutely no reason to think or assume that Equals compares values versus references. It's trivially easy to create such a class, but this is not a language specification.
Post-question-edit edit
Your implementation of Equals will return true for any non-null instance of your class. Though the syntax makes me think that you aren't, you may be confusing the is C# keyword (which confirms type) with the is keyword in VB.NET (which confirms referential equality). If that is indeed the case, then you can make an explicit reference comparison in C# by using Object.ReferenceEquals(this, obj).
In any case, this is why you are seeing true for Equals, since you're passing in a non-null instance of your class.
Incidentally, your comment about NUnit using Equals is true for the same reason; because operators are not polymorphic, there would be no way for a particular class to define custom equality behavior if the Assert function used ==.
a == b checks if they reference the same object.
a.Equals(b) compares the contents.
This is a link to a Jon Skeet article from 2004 that explains it better.
You pretty much answered your question yourself:
I have also over-ridden Equals() in the subclass implementation, which does a very basic check to see whether or not the passed-in object is null and is of the subclass's type. If both those conditions are met, the objects are deemed to be equal.
The == operator hasn't been overloaded - so it's returning false since a and b are different objects. But a.Equals is calling your override, which is presumably returning true because neither a nor b are null, and they're both of the subclass' type.
So your question was "When can a == b be false and a.Equals(b) true?" Your answer in this case is: when you explicitly code it to be so!
In Java a ==b check if the references of the two objects are equals (rougly, if the two objects are the same object "aliased")
a.equals(b) compare the values represented by the two objects.
They both do the same unless they are specifically overloaded within the object to do something else.
A quote from the Jon Skeet Article mentioned elsewhere.
The Equals method is just a virtual
one defined in System.Object, and
overridden by whichever classes choose
to do so. The == operator is an
operator which can be overloaded by
classes, but which usually has
identity behaviour.
The keyword here is USUALLY. They can be written to do whatever the underlying class wishes and in no way do they have to do the same.
The "==" operate tests absolute equality (unless overloaded); that is, it tests whether two objects are the same object. That's only true if you assigned one to the other, ie.
MyObject a = MyObject.Create();
MyObject b = a;
Just setting all the properties of two objects equal doesn't mean the objects themselves are. Under the hood, what the "==" operator is comparing is the addresses of the objects in memory. A practical effect of this is that if two objects are truly equal, changing a property on one of them will also change it on the other, whereas if they're only similar ("Equals" equal), it won't. This is perfectly consistent once you understand the principle.
I believe that a == b will check if the referenced object is the same.
Usually to see if the value is the same a.Equals(b) is used (this often needs to be overridden in order to work).

== or .Equals()

Why use one over the other?
== is the identity test. It will return true if the two objects being tested are in fact the same object. Equals() performs an equality test, and will return true if the two objects consider themselves equal.
Identity testing is faster, so you can use it when there's no need for more expensive equality tests. For example, comparing against null or the empty string.
It's possible to overload either of these to provide different behavior -- like identity testing for Equals() --, but for the sake of anybody reading your code, please don't.
Pointed out below: some types like String or DateTime provide overloads for the == operator that give it equality semantics. So the exact behavior will depend on the types of the objects you are comparing.
See also:
http://blogs.msdn.com/csharpfaq/archive/2004/03/29/102224.aspx
#John Millikin:
Pointed out below: some value types like DateTime provide overloads for the == operator >that give it equality semantics. So the exact behavior will depend on the types of the >objects you are comparing.
To elaborate:
DateTime is implemented as a struct. All structs are children of System.ValueType.
Since System.ValueType's children live on the stack, there is no reference pointer to the heap, and thus no way to do a reference check, you must compare objects by value only.
System.ValueType overrides .Equals() and == to use a reflection based equality check, it uses reflection to compare each fields value.
Because reflection is somewhat slow, if you implement your own struct, it is important to override .Equals() and add your own value checking code, as this will be much faster. Don't just call base.Equals();
Everyone else pretty much has you covered, but I have one more word of advice. Every now and again, you will get someone who swears on his life (and those of his loved ones) that .Equals is more efficient/better/best-practice or some other dogmatic line. I can't speak to efficiency (well, OK, in certain circumstances I can), but I can speak to a big issue which will crop up: .Equals requires an object to exist. (Sounds stupid, but it throws people off.)
You can't do the following:
StringBuilder sb = null;
if (sb.Equals(null))
{
// whatever
}
It seems obvious to me, and perhaps most people, that you will get a NullReferenceException. However, proponents of .Equals forget about that little factoid. Some are even "thrown" off (sorry, couldn't resist) when they see the NullRefs start to pop up.
(And years before the DailyWTF posting, I did actually work with someone who mandated that all equality checks be .Equals instead of ==. Even proving his inaccuracy didn't help. We just made damn sure to break all his other rules so that no reference returned from a method nor property was ever null, and it worked out in the end.)
== is generally the "identity" equals meaning "object a is in fact the exact same object in memory as object b".
equals() means that the objects logically equal (say, from a business point of view). So if you are comparing instances of a user-defined class, you would generally need to use and define equals() if you want things like a Hashtable to work properly.
If you had the proverbial Person class with properties "Name" and "Address" and you wanted to use this Person as a key into a Hashtable containing more information about them, you would need to implement equals() (and hash) so that you could create an instance of a Person and use it as a key into the Hashtable to get the information.
Using == alone, your new instance would not be the same.
According to MSDN:
In C#, there are two different kinds of equality: reference equality (also known as identity) and value equality. Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality. Reference equality means that there are not two objects to compare. Instead, there are two object references and both of them refer to the same object.
...
By default, the operator == tests for reference equality by determining whether two references indicate the same object.
Both Equals and == can be overloaded, so the exact results of calling one or the other will vary. Note that == is determined at compile time, so while the actual implementation could change, which == is used is fixed at compile time, unlike Equals which could use a different implementation based on the run time type of the left side.
For instance string performs an equality test for ==.
Also note that the semantics of both can be complex.
Best practice is to implement equality like this example. Note that you can simplify or exclude all of this depending on how you plan on using you class, and that structs get most of this already.
class ClassName
{
public bool Equals(ClassName other)
{
if (other == null)
{
return false;
}
else
{
//Do your equality test here.
}
}
public override bool Equals(object obj)
{
ClassName other = obj as null; //Null and non-ClassName objects will both become null
if (obj == null)
{
return false;
}
else
{
return Equals(other);
}
}
public bool operator ==(ClassName left, ClassName right)
{
if (left == null)
{
return right == null;
}
else
{
return left.Equals(right);
}
}
public bool operator !=(ClassName left, ClassName right)
{
if (left == null)
{
return right != null;
}
else
{
return !left.Equals(right);
}
}
public override int GetHashCode()
{
//Return something useful here, typically all members shifted or XORed together works
}
}
Another thing to take into consideration: the == operator may not be callable or may have different meaning if you access the object from another language. Usually, it's better to have an alternative that can be called by name.
The example is because the class DateTime implements the IEquatable interface, which implements a "type-specific method for determining equality of instances." according to MSDN.
use equals if you want to express the contents of the objects compared should be equal. use == for primitive values or if you want to check that the objects being compared is one and the same object. For objects == checks whether the address pointer of the objects is the same.
I have seen Object.ReferenceEquals() used in cases where one wants to know if two references refer to the same object
In most cases, they are the same, so you should use == for clarity. According to the Microsoft Framework Design Guidelines:
"DO ensure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics."
https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators
But sometimes, someone will override Object.Equals without providing equality operators. In that case, you should use Equals to test for value equality, and Object.ReferenceEquals to test for reference equality.
If you do disassemble (by dotPeek for example) of Object, so
public virtual bool Equals(Object obj)
described as:
// Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
//
So, is depend on type.
For example:
Object o1 = "vvv";
Object o2 = "vvv";
bool b = o1.Equals(o2);
o1 = 555;
o2 = 555;
b = o1.Equals(o2);
o1 = new List<int> { 1, 2, 3 };
o2 = new List<int> { 1, 2, 3 };
b = o1.Equals(o2);
First time b is true (equal performed on value types), second time b is true (equal performed on value types), third time b is false (equal performed on reference types).

Categories

Resources