Why is equals method on object class virtual? - c#

I was wondering why is Object.Equals(Object obj) virtual. I understand that we can override that method and write our own code for checking equality instead of the base Object.Equals(Object obj) method that checks only reference equality.
What I say is why override it when i can implement my own new method in my defined type? Is there any specific reason?

You would override it for the same reason you would want to override any method rather than hiding it with a new method in a derived class: because of polymorphism. You don't know how your derived class is going to be used by other code which only might know about the base class.
Clients may not even know that you've overridden the class at all, but they do know that they can call Equals on your instances because everything derives from Object. If you have some other, new method, the code using your instances will not know to call that method instead. It's the Liskov Substitution Principle at work.

What I say is why override it when i can implement my own new method in my defined type?
Because that is how the language feature has been designed, as you know every type in C# is inheriting from Object and Object defines the methods with default implementation to check equality of two objects, and we as developers creating new types might want to modify the behavior how equals method compare two objects of specific type.
Here is an example to understand why it is virtual:
int i = 1;
int j = 1;
Object o = i;
o.Equals(j); // now what will happen here if you have'nt overriden it
the int type contains the overriden implementation of Equals method which checks the two integers for equality, so when we will call Equals method using reference of type Object it will call the implementation defined in the type System.Int32,and we had a new method defined in the System.Int32 and not override the Equals method of Object, then we would see unexpected behavior as Object type implementation would have checked the memory addresses i.e reference equality.
Consider this example as well:
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
}
public Person(string name)
{
_name = name;
}
public override string ToString()
{
return _name;
}
}
What if i want Equals method to not compare them by reference but instead we want to compare them on basis of name, in that case we would need to override the Equals method so that calling it either with Object type reference or Person type reference it would return the same result i.e not checking reference equality but checking the Name of two Person class objects.

Related

Why does Equals(object) win over Equals(T) when using an inherited object in Hashset or other Collections?

I am aware of the fact that I always have to override Equals(object) and GetHashCode() when implementing IEquatable<T>.Equals(T).
However, I don't understand, why in some situations the Equals(object) wins over the generic Equals(T).
For example why is the following happening? If I declare IEquatable<T> for an interface and implement a concrete type X for it, the general Equals(object) is called by a Hashset<X> when comparing items of those type against each other. In all other situations where at least one of the sides is cast to the Interface, the correct Equals(T) is called.
Here's a code sample to demonstrate:
public interface IPerson : IEquatable<IPerson> { }
//Simple example implementation of Equals (returns always true)
class Person : IPerson
{
public bool Equals(IPerson other)
{
return true;
}
public override bool Equals(object obj)
{
return true;
}
public override int GetHashCode()
{
return 0;
}
}
private static void doEqualityCompares()
{
var t1 = new Person();
var hst = new HashSet<Person>();
var hsi = new HashSet<IPerson>();
hst.Add(t1);
hsi.Add(t1);
//Direct comparison
t1.Equals(t1); //IEquatable<T>.Equals(T)
hst.Contains(t1); //Equals(object) --> why? both sides inherit of IPerson...
hst.Contains((IPerson)t1); //IEquatable<T>.Equals(T)
hsi.Contains(t1); //IEquatable<T>.Equals(T)
hsi.Contains((IPerson)t1); //IEquatable<T>.Equals(T)
}
HashSet<T> calls EqualityComparer<T>.Default to get the default equality comparer when no comparer is provided.
EqualityComparer<T>.Default determines if T implementsIEquatable<T>. If it does, it uses that, if not, it uses object.Equals and object.GetHashCode.
Your Person object implements IEquatable<IPerson> not IEquatable<Person>.
When you have a HashSet<Person> it ends up checking if Person is an IEquatable<Person>, which its not, so it uses the object methods.
When you have a HashSet<IPerson> it checks if IPerson is an IEquatable<IPerson>, which it is, so it uses those methods.
As for the remaining case, why does the line:
hst.Contains((IPerson)t1);
call the IEquatable Equals method even though its called on the HashSet<Person>. Here you're calling Contains on a HashSet<Person> and passing in an IPerson. HashSet<Person>.Contains requires the parameter to be a Person; an IPerson is not a valid argument. However, a HashSet<Person> is also an IEnumerable<Person>, and since IEnumerable<T> is covariant, that means it can be treated as an IEnumerable<IPerson>, which has a Contains extension method (through LINQ) which accepts an IPerson as a parameter.
IEnumerable.Contains also uses EqualityComparer<T>.Default to get its equality comparer when none is provided. In the case of this method call we're actually calling Contains on an IEnumerable<IPerson>, which means EqualityComparer<IPerson>.Default is checking to see if IPerson is an IEquatable<IPerson>, which it is, so that Equals method is called.
Although IComparable<in T> is contravariant with respect to T, such that any type which implements IComparable<Person> would automatically be considered an implementation of IComparable<IPerson>, the type IEquatable<T> is intended for use with sealed types, especially structures. The requirement that Object.GetHashCode() be consistent with both IEquatable<T>.Equals(T) and Object.Equals(Object) generally implies that the latter two methods should behave identically, which in turn implies that one of them should chain to the other. While there is a large performance difference between passing a struct directly to an IEquatable<T> implementation of the proper type, compared with constructing a instance of the structure's boxed-heap-object type and having an Equals(Object) implementation copy the structure data out of that, no such performance different exists with reference types. If IEquatable<T>.Equals(T) and Equals(Object) are going to be equivalent and T is an inheritable reference type, there's no meaningful difference between:
bool Equals(MyType obj)
{
MyType other = obj as MyType;
if (other==null || other.GetType() != typeof(this))
return false;
... test whether other matches this
}
bool Equals(MyType other)
{
if (other==null || other.GetType() != typeof(this))
return false;
... test whether other matches this
}
The latter could save one typecast, but that's unlikely to make a sufficient performance difference to justify having two methods.

Distinct() not calling equals methods

I've implemented IEqualityComparer and IEquatable (both just to be sure), but when I call the Distinct() method on a collection it does not call the methods that come with it. Here is the code that I execute when calling Distinct().
ObservableCollection<GigViewModel> distinctGigs = new ObservableCollection<GigViewModel>(Gigs.Distinct<GigViewModel>());
return distinctGigs;
I want to return an ObservableCollection that doesn't contain any double objects that are in the 'Gigs' ObservableCollection.
I implement the interfaces like this on the GigViewModel class:
public class GigViewModel : INotifyPropertyChanged, IEqualityComparer<GigViewModel>, IEquatable<GigViewModel>
{
....
}
And override the methods that come with the interfaces like so:
public bool Equals(GigViewModel x, GigViewModel y)
{
if (x.Artiest.Naam == y.Artiest.Naam)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(GigViewModel obj)
{
return obj.Artiest.Naam.GetHashCode();
}
public bool Equals(GigViewModel other)
{
if (other.Artiest.Naam == this.Artiest.Naam)
{
return true;
}
else
{
return false;
}
}
Thanks for all the help I'm getting. So I've created a seperate class that implements IEqualityComparer and passed it's instance into the disctinct method. But the methods are still not being triggered.
EqualityComparer:
class GigViewModelComparer : IEqualityComparer<GigViewModel>
{
public bool Equals(GigViewModel x, GigViewModel y)
{
if (x.Artiest.Naam == y.Artiest.Naam)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(GigViewModel obj)
{
return obj.Artiest.Naam.GetHashCode();
}
}
The Distinct() call:
GigViewModelComparer comp = new GigViewModelComparer();
ObservableCollection<GigViewModel> distinctGigs = new ObservableCollection<GigViewModel>(Gigs.Distinct(comp));
return distinctGigs;
EDIT2:
The GetHashCode() method DOES get called! After implementing the new class. But the collection still contains duplicates. I have a list of 'Gigs' that contain an 'Artiest' (or Artist) object. This Artist has a Naam property which is a String (Name).
So you had the object that itself is being compared implement both IEquatable as well as IEqualityComparer. That generally doesn't make sense. IEquatable is a way of saying an object can compare itself to something else. IEqualityComparer is a way of saying it can compare two different things you give it to each other. You generally want to do one or the other, not both.
If you want to implement IEquatable then the object not only needs to have an Equals method of the appropriate signature, but it needs to override GetHashCode to have a sensible implementation for the given definition of equality. You didn't do that. You created GetHashCode method that takes an object as a parameter, but that's the overload used for IEqualityComparer. You need to override the parameter-less version when using IEquatable (the one defined in Object).
If you want to create a class that implements IEqualityComparer you need to pass the comparer to the Distinct method. Since you've defined the object as its own comparer you'd need to pass in some instance of this object as the second parameter. Of course, this doesn't really make a whole lot of sense this way; so it would be better, if you go this route, to pull out the two methods that go with IEqualityComparer into a new type, and create an instance of that type to the Distinct method. If you actually passed an object with those definitions in as a comparer, it'd work just fine.
Following MSDN's advice, you'd be best off creating a separate class for your equality comparisons:
We recommend that you derive from the EqualityComparer class
instead of implementing the IEqualityComparer interface, because
the EqualityComparer class tests for equality using the
IEquatable.Equals method instead of the Object.Equals method. This
is consistent with the Contains, IndexOf, LastIndexOf, and Remove
methods of the Dictionary class and other generic
collections.
So, create a class, GigViewModelComparer, that derives from EqualityComparer and put your Equals and GetHashCode methods there.
Then, pass in an instance of that new comparer class in your call to Gigs.Distinct(new GigViewModelComparer()) and it should work. Follow along in the example in the MSDN link I provided above.
I've never seen somebody implement IEqualityComparer in the same class as the type of objects the collection in question contains, that is probably at least part of your problem.

What is the significance of the ToString() method?

Could someone please explain this for me, how this even work??
How is it even possible to return anything out of ToString(), without creating an actual method?
using System;
namespace ConsoleApplication4
{
class Person
{
private string name;
private int age;
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
**/*
* What is ToString() method?
* What I am overriding Here?
*/**
public override string ToString()
{
return "Name= " + Name + " Age=" + Age;
}
}
class Sample
{
static void Main(string[] args)
{
Person P1 = new Person();
P1.Name = "ABC";
P1.Age = 21;
Console.WriteLine(P1.ToString());
Console.ReadLine();
**//Ouput Name = ABC Age = 23**
}
}
}
All classes and structs in C# derive implicitly from System.Object. You are overriding Object.ToString.
In C#, when you write:
class Person
{
It's effectively the same as writing
class Person : System.Object
{
How is it even possible to return anything out of ToString(), without creating an actual method?
If you don't override ToString, you'll get the default implementation provided by System.Object.ToString().
The implicit base class being System.Object is documented in 4.2.2 of the C# language spec:
The object class type is the ultimate base class of all other types. Every type in C# directly or indirectly derives from the object class type.
The keyword object is simply an alias for the predefined class System.Object.
Note that it's slightly different with a custom struct, since value types derive from System.ValueType, but System.Object is still part of the inheritance hierarchy.
This is documented in 4.1.1 of the C# language spec:
All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (ยง10.1.1.2).
Note that System.ValueType is not itself a value-type. Rather, it is a class-type from which all value-types are automatically derived.
how is it even possible to return anything out of ToString(), without creating an actual method
The default implementation of Object.ToString() is simply:
return GetType().ToString();
This returns the (unqualified) name of the type. If you had not overridden it on your Person class, then it would have returned "Person".
Subclasses are free to override this method to return a more useful string, which might include some of the object's state, or even a human-friendly representation of the object. (DateTime does this, for example.)
public override string is creating a method, it just happens to already exist, thus the override keyword is used to denote that you are redefining a method in the parent class (System.Object).
More info here: http://msdn.microsoft.com/en-us/library/system.object.aspx
Because all classes in the .NET Framework are derived from Object,
every method defined in the Object class is available in all objects
in the system. Derived classes can and do override some of these
methods, including:
Equals - Supports comparisons between objects.
Finalize - Performs cleanup operations before an object is automatically reclaimed.
GetHashCode - Generates a number corresponding to the value of the object to support the use of a hash table.
ToString - Manufactures a human-readable text string that describes an instance of the class.

How to detect current type has "ToString" overrided method or not? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to determine if the MethodInfo is an override of the base method
Normally, when we execute "ToString" method of any complex type it will return current type name like the following string except there is "ToString" overrided method.
System.Data.Entity.DynamicProxies.UserRole_D77A004638495805D68478322DF47F48540438D82DC9A5A0E1B0B2A181E4A100
I want some logic to detect current type about this because I try to export data to excel format. But some property of model is complex type that doesn't define "ToString" method. Output of this property is useless for normal user.
Thanks,
You can check the DeclaringType on the methodInfo of to string
if (methodInfo.DeclaringType != typeof(YourObject)) {
...
}
system.reflection.methodinfo
You can of course do this with reflection. An alternative approach that might give you what you want and doesn't use reflection is:
if (this.ToString() != this.GetType().ToString())
{
// This Type or one of its base types has overridden object.ToString()
}
Note that you probably want to check if the current type or any base type (except object) has overridden ToString(). As a contrived example all types derived from Exception return a sensible value from ToString() (exception details including stack trace), but not all override Exception.ToString().
I think this approach to check whether particular type overrides ToString or not is a little bit brittle. We can solve this in several other ways.
First of all if string representation is required you can add additional mixin interface like IObjectDescriptor with one method: string GetDescription. And you can require this implentation from every type (and if class is not implements it throw an exception).
Second approach (if we don't want to change existing code base) is use separate helper class that will have one method: ConvertToString:
static class ToStringHelper
{
// We can use Generic method to prevent boxing
public string ConvertToString(object o)
{
var sb = new StringBuilder();
// using reflection to access all public properties, for example
return sb.ToString();
}
}
In both cases your intention and "contract" between you and your clients would be much more clear. In first case you'll throw an exception if type is not implements particular interface, with second approach you'll get at least consistent behavior.
You can use IsSubclassOf object and DeclaringType of method.
public class BaseClass
{
public string Name;
public virtual void Write(string val)
{
}
}
public class SubClass : BaseClass
{
public string Address;
public override void Write(string val)
{
base.Write(val);
}
}
Test code:
Type objType = obj.GetType();
MethodInfo info = objType.GetMethod("Write");
if (objType.IsSubclassOf(info.DeclaringType))
{
Console.WriteLine("Not Override");
}
else
Console.WriteLine("Override");

Internals of "equals" in .NET

I have a foolish doubt.Generally "System.Object" implements "Equals". When I implements
IEquatable interface i can give custom definition ( I believe so) to my "Equals".
so the professor class implementation is equal to
class Professor:System.Object,IEquatable
since there are different definitions of System.Equals ,and IEquatable's Equals ,Why did not C# report error?.Because I am not overriding "Equals" and even not Hiding "Equals" using new keyword.
class Professor : IEquatable<Professor>
{
public string Name { get; set; }
public bool Equals(Professor cust)
{
if (cust == null) return false;
return cust.Name == this.Name;
}
}
You are neither overriding nor hiding Object.Equals() because your version takes Professor as a parameter type - not object. Your are overloading the Equals() method.
C# allows two methods with the same name to differ on the type of the argument(s) that they accept. This is referred to as overloading - it can be viewed as compile-time polymorphism.
Overriding (which you could, and probably should also do) alters the implementation of a method from its version in a base class. It is the basis for runtime type polymorphism.
Hiding is a less common technique that allows a derived class to mask a version of a method in a base class. Based on the type of the reference through which you make the call, you may either get the base class version (if called through a base class reference) or the derived class version (if called through a derived type reference).
On your second question, you should use IEquatable<T> when there are semantics for comparing 'equality' of two instances that is separate from reference equality.
You should implement IComparable or IComparable<T> when there are semantics for ordering items. Meaning they can be less than, greater than, or equivalent.
The Object.Equals method accepts an object of type 'object' as its parameter. Your Equals method accepts an object of type 'Professor' as its parameter. Both of these methods can co-exist because it is legal to differ two identically-named methods by their parameter list; this is call method overloading.
You don't need to explicitly implement IEquatable if all you want to do is override the default Equals() implementation.
You can just do something like this:
class Professor
{
public string Name { get; set; }
public override bool Equals(object cust)
{
if (cust == null || !(cust is Professor)) return false;
return cust.Name == this.Name;
}
}
Be aware that if you override Equals() you also should override GetHashCode() to ensure proper operation of dictionaries and other collections that make use of hashing to differentiate between objects. Here's the MSDN page guidelines for overriding Equals().

Categories

Resources