Collection<t>.IndexOf and overloaded ==</t>
-
Ok, I've Googled myself silly... In my base class I overload the
==
operator
(includingGetHashCode
,!=
andEquals
) and when I do acustomerA == customerB
it works 100%, yet when I do acustomersList.IndexOf(customerA)
I always get -1 even though I can see a customer instance in the list that should return true in my overloaded operator, and when I place a break point in my operator overloader it stops when I do a==
, but it does not break when I do anIndexOf()
... Help please...____________________________________________________________ Be brave little warrior, be VERY brave
-
Ok, I've Googled myself silly... In my base class I overload the
==
operator
(includingGetHashCode
,!=
andEquals
) and when I do acustomerA == customerB
it works 100%, yet when I do acustomersList.IndexOf(customerA)
I always get -1 even though I can see a customer instance in the list that should return true in my overloaded operator, and when I place a break point in my operator overloader it stops when I do a==
, but it does not break when I do anIndexOf()
... Help please...____________________________________________________________ Be brave little warrior, be VERY brave
This method determines equality using the default equality comparer EqualityComparer(T).Default for T, the type of values in the list. (http://msdn.microsoft.com/en-us/library/e4w08k17.aspx[^]) You'll need to implement IEqualityComparer[^] in your base class
only two letters away from being an asset
-
Ok, I've Googled myself silly... In my base class I overload the
==
operator
(includingGetHashCode
,!=
andEquals
) and when I do acustomerA == customerB
it works 100%, yet when I do acustomersList.IndexOf(customerA)
I always get -1 even though I can see a customer instance in the list that should return true in my overloaded operator, and when I place a break point in my operator overloader it stops when I do a==
, but it does not break when I do anIndexOf()
... Help please...____________________________________________________________ Be brave little warrior, be VERY brave
-
Ok, I've Googled myself silly... In my base class I overload the
==
operator
(includingGetHashCode
,!=
andEquals
) and when I do acustomerA == customerB
it works 100%, yet when I do acustomersList.IndexOf(customerA)
I always get -1 even though I can see a customer instance in the list that should return true in my overloaded operator, and when I place a break point in my operator overloader it stops when I do a==
, but it does not break when I do anIndexOf()
... Help please...____________________________________________________________ Be brave little warrior, be VERY brave
Found the (strange) answer...
==
,.Equals()
and!=
works fine if you implement in the base object, but to be able to overload forCollection.IndexOf()
you MUST implementIEquatable
on theCustomer
object, not on the base... If this makes sense to anybody please explain to me as I'n jealous... PS: I'm working in Silverlight 3, please tell me this is not a SL 3 issue...____________________________________________________________ Be brave little warrior, be VERY brave
-
This method determines equality using the default equality comparer EqualityComparer(T).Default for T, the type of values in the list. (http://msdn.microsoft.com/en-us/library/e4w08k17.aspx[^]) You'll need to implement IEqualityComparer[^] in your base class
only two letters away from being an asset
Mark Nischalke wrote:
You'll need to implement IEqualityComparer[^] in your base class
Hi Mark, I found that implementing this in my base class did not give me what I needed, implementing it in my actual (child) class however gave me what I needed, does that make sense to you?
____________________________________________________________ Be brave little warrior, be VERY brave
-
hi first what kind of type is your customer list ?? is it a generic list or just a arraylist containing objects?!? overload the customerlist operators too for correct comparing i would suggest :) greetz
I'm using a ObservableCollection as generated for the Silverlight 3 Service in the Proxy...
____________________________________________________________ Be brave little warrior, be VERY brave
-
Mark Nischalke wrote:
You'll need to implement IEqualityComparer[^] in your base class
Hi Mark, I found that implementing this in my base class did not give me what I needed, implementing it in my actual (child) class however gave me what I needed, does that make sense to you?
____________________________________________________________ Be brave little warrior, be VERY brave
Show what you have done and maybe someone can give you advice.
only two letters away from being an asset
-
Show what you have done and maybe someone can give you advice.
only two letters away from being an asset
Its a rather elaborate thing, would have to create a new project to explain in one shot. Will have to try explain tomorrow, need to go now
____________________________________________________________ Be brave little warrior, be VERY brave
-
Found the (strange) answer...
==
,.Equals()
and!=
works fine if you implement in the base object, but to be able to overload forCollection.IndexOf()
you MUST implementIEquatable
on theCustomer
object, not on the base... If this makes sense to anybody please explain to me as I'n jealous... PS: I'm working in Silverlight 3, please tell me this is not a SL 3 issue...____________________________________________________________ Be brave little warrior, be VERY brave
I think I might be able to explain, but it depends on your current code. From reading your posts, you seem to have something like this:
public class Base : IEquatable<Base>
{
public static bool operator==(...)
{
...
}//other associated overrides
}
public class Derived : Base
{
//no overrides in this class
}The question is, do you have
Collection<Base>
orCollection<Derived>
? If you use Reflector to dig through the EqualityComparer code, you will see that it checks forIEquatable<T>
where T is the exact type of the collection. Thus, if you have a collection of Derived, I would expect you to need to implement IEquatable on Derived. Since you have only implementedIEquatable<Base>
, the check forIEquatable<Derived>
will fail and you will fall back to the default implementation. Though, if you overrode the Equals inherited from object, I would think it should get called from the default comparer. -
I think I might be able to explain, but it depends on your current code. From reading your posts, you seem to have something like this:
public class Base : IEquatable<Base>
{
public static bool operator==(...)
{
...
}//other associated overrides
}
public class Derived : Base
{
//no overrides in this class
}The question is, do you have
Collection<Base>
orCollection<Derived>
? If you use Reflector to dig through the EqualityComparer code, you will see that it checks forIEquatable<T>
where T is the exact type of the collection. Thus, if you have a collection of Derived, I would expect you to need to implement IEquatable on Derived. Since you have only implementedIEquatable<Base>
, the check forIEquatable<Derived>
will fail and you will fall back to the default implementation. Though, if you overrode the Equals inherited from object, I would think it should get called from the default comparer.Hi Gideon, thanks, that explains why it works the way it does, but doesn't explain why it doesn't use
==
or.Equals()
:) Not sure why there are so many ways to check equality... Or why.IndexOf()
has to useIEquatable<Derived>
when other methods does not... Anyway, thanks for the description, makes sense____________________________________________________________ Be brave little warrior, be VERY brave
-
Hi Gideon, thanks, that explains why it works the way it does, but doesn't explain why it doesn't use
==
or.Equals()
:) Not sure why there are so many ways to check equality... Or why.IndexOf()
has to useIEquatable<Derived>
when other methods does not... Anyway, thanks for the description, makes sense____________________________________________________________ Be brave little warrior, be VERY brave
I believe the C# operators like "==" are only visible to the C# compiler, and are not visible to the underlying .Net library. As for why there are so many different types of equality, I think the idea is that there are different 'qualities' of equality. For example, for some purposes, the string "ABC" may be regarded as equal to "abc" or even "åbç", while in others it must be regarded as different. I'm not sure the exact logic behind which functions are used where in .Net; I can certainly imagine that it would be useful to be able to specify a definition of equality which did not require two objects to have the same GetHashCode value (since such a value must be optimized for one particular definition of equality); I'm not sure whether any of the defined equality functions use such a definition.
-
Hi Gideon, thanks, that explains why it works the way it does, but doesn't explain why it doesn't use
==
or.Equals()
:) Not sure why there are so many ways to check equality... Or why.IndexOf()
has to useIEquatable<Derived>
when other methods does not... Anyway, thanks for the description, makes sense____________________________________________________________ Be brave little warrior, be VERY brave
There are so many ways to check equality because there are so many situations that need to be handled. Jared Parsons wrote a nice set of articles that explain some of this topic. The link is to the last article in the set, each of which links to the article before (in typical blog fashion). One reason to have more than just the operator is because the operator must be a static method. This means that which operator to call depends on the compile-time type of the variable instead of the using the runtime-type like a virtual method (such as Equals) would. Also, because they are static, operators cannot be defined on interfaces. So if you need equality methods on an interface, you have to have instance methods. An advantage of the IEqualityComparer interface is that you can have a different condition for "equality" in different situations for the same type. In one case, you may only check the name, but in another you may want to check both the name and the age. This would be impossible with just the operator or overriden virtual method, but is possible to do with the extra interface. (A similar reasoning can be given for having both IComparer and IComparable for sorting.) C# has a particularly nasty problem when it comes to == vs .Equals(). In C#, if you write
if (a == b) { ... }
when there is no overloaded operator for the types of variables a and b, the compiler will check to see if the are both references to the same object. In VB however, writingIf a = b Then ...
when there is no overloaded operator, a compile error will occur. To see if a and b are references to the same object, you use the Is and IsNot operators.Collection<Derived>.IndexOf
has to useIEquatable<Derived>
because it was written without any knowledge of what your classes will be. The alternative would involve a bunch of messy reflection code that would cause horrible performance and would probably not be useful in most situations. All the other places where you are using == and Equals, the compiler knows about and will use your methods since they are the best match. Out of curiosity, did you both implement the Equals forIEquatable<Base>
and override the Equals from object?public class Base : IEquatable<Base>
{
public static bool operator==(...)
{
...
}//this method is for IEquatable pu
-
I believe the C# operators like "==" are only visible to the C# compiler, and are not visible to the underlying .Net library. As for why there are so many different types of equality, I think the idea is that there are different 'qualities' of equality. For example, for some purposes, the string "ABC" may be regarded as equal to "abc" or even "åbç", while in others it must be regarded as different. I'm not sure the exact logic behind which functions are used where in .Net; I can certainly imagine that it would be useful to be able to specify a definition of equality which did not require two objects to have the same GetHashCode value (since such a value must be optimized for one particular definition of equality); I'm not sure whether any of the defined equality functions use such a definition.
Actually, the operators are visible to all languages. They are actually defined as methods with names such as op_Equality, op_Inequality, etc. and other languages can use their operators to call those methods. You are on the right track as far as qualities of equality, though strings are a weird case where there are quite a few different "levels" of equality. My response below explains what I see as reasons for different equality methods if you are interested.
-
There are so many ways to check equality because there are so many situations that need to be handled. Jared Parsons wrote a nice set of articles that explain some of this topic. The link is to the last article in the set, each of which links to the article before (in typical blog fashion). One reason to have more than just the operator is because the operator must be a static method. This means that which operator to call depends on the compile-time type of the variable instead of the using the runtime-type like a virtual method (such as Equals) would. Also, because they are static, operators cannot be defined on interfaces. So if you need equality methods on an interface, you have to have instance methods. An advantage of the IEqualityComparer interface is that you can have a different condition for "equality" in different situations for the same type. In one case, you may only check the name, but in another you may want to check both the name and the age. This would be impossible with just the operator or overriden virtual method, but is possible to do with the extra interface. (A similar reasoning can be given for having both IComparer and IComparable for sorting.) C# has a particularly nasty problem when it comes to == vs .Equals(). In C#, if you write
if (a == b) { ... }
when there is no overloaded operator for the types of variables a and b, the compiler will check to see if the are both references to the same object. In VB however, writingIf a = b Then ...
when there is no overloaded operator, a compile error will occur. To see if a and b are references to the same object, you use the Is and IsNot operators.Collection<Derived>.IndexOf
has to useIEquatable<Derived>
because it was written without any knowledge of what your classes will be. The alternative would involve a bunch of messy reflection code that would cause horrible performance and would probably not be useful in most situations. All the other places where you are using == and Equals, the compiler knows about and will use your methods since they are the best match. Out of curiosity, did you both implement the Equals forIEquatable<Base>
and override the Equals from object?public class Base : IEquatable<Base>
{
public static bool operator==(...)
{
...
}//this method is for IEquatable pu
wow. there seems to be a lot hidden behind a simple == concept. I'll have to read your reply a couple more times. It does shed some light on this thread[^]. Thanks.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
-
There are so many ways to check equality because there are so many situations that need to be handled. Jared Parsons wrote a nice set of articles that explain some of this topic. The link is to the last article in the set, each of which links to the article before (in typical blog fashion). One reason to have more than just the operator is because the operator must be a static method. This means that which operator to call depends on the compile-time type of the variable instead of the using the runtime-type like a virtual method (such as Equals) would. Also, because they are static, operators cannot be defined on interfaces. So if you need equality methods on an interface, you have to have instance methods. An advantage of the IEqualityComparer interface is that you can have a different condition for "equality" in different situations for the same type. In one case, you may only check the name, but in another you may want to check both the name and the age. This would be impossible with just the operator or overriden virtual method, but is possible to do with the extra interface. (A similar reasoning can be given for having both IComparer and IComparable for sorting.) C# has a particularly nasty problem when it comes to == vs .Equals(). In C#, if you write
if (a == b) { ... }
when there is no overloaded operator for the types of variables a and b, the compiler will check to see if the are both references to the same object. In VB however, writingIf a = b Then ...
when there is no overloaded operator, a compile error will occur. To see if a and b are references to the same object, you use the Is and IsNot operators.Collection<Derived>.IndexOf
has to useIEquatable<Derived>
because it was written without any knowledge of what your classes will be. The alternative would involve a bunch of messy reflection code that would cause horrible performance and would probably not be useful in most situations. All the other places where you are using == and Equals, the compiler knows about and will use your methods since they are the best match. Out of curiosity, did you both implement the Equals forIEquatable<Base>
and override the Equals from object?public class Base : IEquatable<Base>
{
public static bool operator==(...)
{
...
}//this method is for IEquatable pu
Hi Gideon, Thanks for the explination, I think I fully understand it now, but I will do more reading on it. All I did was to override
==
andEquals
in my base class (which obviously did not give me the correct behaviour), then after much searching I implemented IEquatable<Derived> on my derived class and it worked fine so I stopped working on it. Should I try to implement IEquatable<Base> and see if that gives the correct behaviour? (The attributes I'm comparing on is part of the Base, infact I use the overloaded==
to compare)____________________________________________________________ Be brave little warrior, be VERY brave