Newbie here. I read the following code at Microsoft docs. You can see the webpage here: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.find?view=net-6.0
public class Part : IEquatable<Part>
{
public string PartName { get; set; }
public int PartId { get; set; }
//other code
public override bool Equals(object obj)
{
if (obj == null) return false;
Part objAsPart = obj as Part;
if (objAsPart == null) return false;
else return Equals(objAsPart);
}
// other code
public bool Equals(Part other)
{
if (other == null) return false;
return (this.PartId.Equals(other.PartId));
}
}
public class Example
{
public static void Main()
{
// Create a list of parts.
List<Part> parts = new List<Part>();
// Add parts to the list.
parts.Add(new Part() { PartName = "crank arm", PartId = 1234 });
parts.Add(new Part() { PartName = "chain ring", PartId = 1334 });
parts.Add(new Part() { PartName = "regular seat", PartId = 1434 });
parts.Add(new Part() { PartName = "banana seat", PartId = 1444 });
parts.Add(new Part() { PartName = "cassette", PartId = 1534 });
parts.Add(new Part() { PartName = "shift lever", PartId = 1634 }); ;
//other code
// Check the list for part #1734. This calls the IEquatable.Equals method
// of the Part class, which checks the PartId for equality.
Console.WriteLine("\nContains: Part with Id=1734: {0}",
parts.Contains(new Part { PartId = 1734, PartName = "" }));
}
}
Now, my question is about parts.Contains(new Part { PartId = 1734, PartName = "" })
line.
This is the ListT.Contains(T)
method.
As you can see from the Microsoft reference source (here: https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,521b9f7129105e15), the code for Contains
method is the following:
public bool Contains(T item) {
if ((Object) item == null) {
for(int i=0; i<_size; i++)
if ((Object) _items[i] == null)
return true;
return false;
}
else {
EqualityComparer<T> c = EqualityComparer<T>.Default;
for(int i=0; i<_size; i++) {
if (c.Equals(_items[i], item)) return true;
}
return false;
}
}
So as you can see Contains
method uses Equals
method, but which Equals
of all?
c.Equals(_items[i], item)
means that the method we are calling belongs to EqualityComparer<T>.Default
.
Indeed Default
is a property of EqualityComparer<T>
class and it returns an object of the same class.
So the Equals
we see here should belong to the EqualityComparer<T>
class.
Question #1: How can we have an object of EqualityComparer<T>
class since this class is abstract?
Question #2: How can we call c.Equals(_items[i], item)
since this method is also abstract? (as you can see here: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.equalitycomparer-1.equals?view=net-6.0
But the most important of all,
Question #3: How do we go from c.Equals(_items[i], item)
method of class EqualityComparer<T>
, to the IEquatable.Equals
method which is implemented in the Part
class. Does the first method invoke the second?
Here: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.equalitycomparer-1?view=net-6.0 it says the following:
"The
Default
property checks whether typeT
implements theSystem.IEquatable<T>
generic interface and, if so, returns anEqualityComparer<T>
that invokes the implementation of theIEquatableT.Equals
method. Otherwise, it returns anEqualityComparer<T>
, as provided byT
."
I don't understand how the second method, IEquatable.Equals
, is invoked.
I am sorry for the long post. Thanks in advance!