Update* I am so sorry... my sample code contained an error which resulted in a lot of answers I didn't understand. In stead of
Console.WriteLine("3. this.Equals " + (go1.Equals(go2)));
I meant to write
Console.WriteLine("3. this.Equals " + (go1.Equals(sb2)));
I'm trying to figure out how I can successfully determine if two generic type values are equal to each other. Based on Mark Byers' answer on this question I would think I can just use value.Equals()
where value is a generic type.
My actual problem is in a LinkedList implementation, but the problem can be shown with this simpler example.
class GenericOjbect<T> {
public T Value { get; private set; }
public GenericOjbect(T value) {
Value = value;
}
public bool Equals(T value) {
return (Value.Equals(value));
}
}
Now I define an instance of GenericObject<StringBuilder>
containing new StringBuilder("StackOverflow")
. I would expect to get true
if I call Equals(new StringBuilder("StackOverflow")
on this GenericObject instance, but I get false
.
A sample program showing this:
using System;
using System.Text;
class Program
{
static void Main()
{
var sb1 = new StringBuilder("StackOverflow");
var sb2 = new StringBuilder("StackOverflow");
Console.WriteLine("StringBuilder compare");
Console.WriteLine("1. == " + (sb1 == sb2));
Console.WriteLine("2. Object.Equals " + (Object.Equals(sb1, sb2)));
Console.WriteLine("3. this.Equals " + (sb1.Equals(sb2)));
var go1 = new GenericOjbect<StringBuilder>(sb1);
var go2 = new GenericOjbect<StringBuilder>(sb2);
Console.WriteLine("\nGenericObject compare");
Console.WriteLine("1. == " + (go1 == go2));
Console.WriteLine("2. Object.Equals " + (Object.Equals(go1, sb2)));
Console.WriteLine("3. this.Equals " + (go1.Equals(sb2)));
Console.WriteLine("4. Value.Equals " + (go1.Value.Equals(sb2.Value)));
}
}
For the three methods of comparing two StringBuilder objects, only the StringBuilder.Equals instance method (the third line) returns true
. This is what I expected. But when comparing the GenericObject objects, its Equals() method (the third line) returns false
. Interestingly enough, the fourth compare method does return true
. I'd think the third and fourth comparison are actually doing the same thing.
I would have expected true
. Because in the Equals() method of the GenericObject class, both value
and Value
are of type T
which in this case is a StringBuilder
. Based on Mark Byers' answer in this question, I would've expected the Value.Equals()
method to be using the StringBuilder's Equals() method. And as I've shown, the StringBuilder's Equal() method does return true
.
I've even tried
public bool Equals(T value) {
return EqualityComparer<T>.Default.Equals(Value, value);
}
but that also returns false.
So, two questions here:
true
?Equals
method so it does return true
?The Swift standard library defines a protocol called Equatable , which requires any conforming type to implement the equal to operator ( == ) and the not equal to operator ( != ) to compare any two values of that type. All of Swift's standard types automatically support the Equatable protocol.
If you need to compare objects of type T by more or less, then the IComparable<T> interface will do. Such a comparison is necessary, for example, when sorting. If you need to compare objects of type T for equality/inequality, you can use the IEquatable<T> interface.
Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.
You can't inherit from the generic type parameter. C# generics are very different from C++ templates. Inheriting from the type parameter requires the class to have a completely different representation based on the type parameter, which is not what happens with . NET generics.
As suggested in Marc Gravell's answer, the problem is with StringBuilder
Equals(object)
implementation that is different to the one in Equals(StringBuilder)
.
Then, you can ignore the problem because your code will work with any other coherently-implemented classes, or you can use dynamic to fix the problem (again as suggested by Mark Gravell).
But, given that you are not using C# 4 (so no dynamic), you can try in this way:
public bool Equals(T value)
{
// uses Reflection to check if a Type-specific `Equals` exists...
var specificEquals = typeof(T).GetMethod("Equals", new Type[] { typeof(T) });
if (specificEquals != null &&
specificEquals.ReturnType == typeof(bool))
{
return (bool)specificEquals.Invoke(this.Value, new object[]{value});
}
return this.Value.Equals(value);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With