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.WriteLin
As Eric Lippert says in answer to this question - Overload resolution is performed at compile time.
If you take a look at StringBuilder
's implementation you will notice it overloads Equals
and does not override it. This is basically the root of the problem as to why StringBuilder.Equals
does not work as you expected in your example.
Take the following 2 classes as example. Overloader
is analogous to StringBuilder
in the example as it overloads Equals
. Overrider
is very similar except it it overrides Equals
instead.
public class Overloader
{
public string Str {get;private set;}
public Overloader (string str) {Str = str;}
public bool Equals( Overloader str )
{
return this.Str.Equals( str );
}
}
public class Overrider
{
public string Str {get;private set;}
public Overrider (string str) {Str = str;}
public override bool Equals( object obj )
{
if ( obj is Overrider )
{
return this.Str.Equals( (obj as Overrider).Str );
}
return base.Equals( obj );
}
}
I have slightly modified your GenericObject
class in my example:
class GenericOjbect
{
public T Value {get;private set;}
public GenericOjbect( T val ) {Value = val;}
public bool Equals( T val )
{
return Value.Equals( val );
}
public override bool Equals( object obj )
{
if ( obj is T )
{
return this.Equals( ( T )obj );
}
if (obj != null && obj is GenericOjbect )
{
return this.Equals( ( obj as GenericOjbect ).Value );
}
return base.Equals( obj );
}
}
In this sample program you will see that Overloader
(or Stringbuilder
for that matter) will return false. However, Overrider
returns true.
class Program
{
static void Main( string[] args )
{
var goOverloader1 = new GenericOjbect( new Overloader( "StackOverflow" ) );
var goOverloader2 = new GenericOjbect( new Overloader( "StackOverflow" ) );
var goOverrider1 = new GenericOjbect( new Overrider( "StackOverflow" ) );
var goOverrider2 = new GenericOjbect( new Overrider( "StackOverflow" ) );
Console.WriteLine( "Overrider : {0}", goOverloader1.Equals( goOverloader2 ) ); //False
Console.WriteLine( "Overloader : {0}", goOverrider1.Equals( goOverrider2 ) ); //True
}
}
Referencing Eric Lippert again - Overload resolution is performed at compile time. Meaning that the compiler basically looks at your GenericObject
like this:
public bool Equals( T val )
{
return Value.Equals( (Object) val );
}
To anwser your question How to determine if two generic type values are equal?. There's two things you possibly could do.
GenericObject
ensure they all at least override Equals
.GenericObject.Equals(T val)
to manually perform late binding.