Groups | Blog | Home
all groups > c# > april 2008 >

c# : Generics and comparison (follow on from my previous "Generics and collections" thread)


Rudy Velthuis
4/4/2008 11:19:24 AM
[quoted text, click to view]

You'll have to put a constraint on T (where clause), so that it only
applies to instances that implement IEquitable<T>, and then use
IEquitable<T>.Equals() to check for equality.

You can also, somehow, omit the constraint and provide the class an
instance of IComparer or IEqualityComparer, to do the work for you.
That has advantages, but also disadvantages.
--
Rudy Velthuis http://rvelthuis.de

Rudy Velthuis
4/4/2008 12:13:23 PM
[quoted text, click to view]

That is a problem with the implementation of the interface for that
particular instantiation of T, then. If it were correctly implemented,
that should not happen.
--
Rudy Velthuis http://rvelthuis.de

"Sailors ought never to go to church. They ought to go to hell,
Martin Robins
4/4/2008 5:53:12 PM
Marc has sorted my problem with the collections, however I am now in a =
new scenario; I am trying to compare a generic property value before =
setting it as shown below ...

public T Value {
get { return this.value; }
set {
if ( this.value !=3D value ) {
this.value =3D value;
this.OnValueChanged(EventArgs.Empty);
}
}
}

This code produces the Operator '=3D=3D' cannot be applied to operands =
of type 'T' and 'T' error at compile time!
I am sure that I am not the only person to have tried this, any clues as =
to the correct work around?

I have tried restricting 'T' to IComparable in a where clause and then =
casting 'this.value' and 'value' to IComparable for the comparison - the =
code then compiles but is this the right answer? It feels wrong, but I =
am quickly learning that my own understanding of generics is much lower =
than I thought it was!

Martin Robins
4/4/2008 7:25:15 PM
Though it compiles, the original IComparable idea did not work; the =
comparisons would often return incorrect results.

I have resolved it for now using "if ( this.value =3D=3D null ? value =
!=3D null : !this.value.Equals(value) )" but I am still open to a better =
way if it exists ...

Martin.

"Martin Robins" <martin at orpheus-solutions dot co dot uk> wrote in =
message news:ujRpfRnlIHA.536@TK2MSFTNGP06.phx.gbl...
Marc has sorted my problem with the collections, however I am now in a =
new scenario; I am trying to compare a generic property value before =
setting it as shown below ...

public T Value {
get { return this.value; }
set {
if ( this.value !=3D value ) {
this.value =3D value;
this.OnValueChanged(EventArgs.Empty);
}
}
}

This code produces the Operator '=3D=3D' cannot be applied to operands =
of type 'T' and 'T' error at compile time!
I am sure that I am not the only person to have tried this, any clues =
as to the correct work around?

I have tried restricting 'T' to IComparable in a where clause and then =
casting 'this.value' and 'value' to IComparable for the comparison - the =
code then compiles but is this the right answer? It feels wrong, but I =
am quickly learning that my own understanding of generics is much lower =
than I thought it was!

Martin Robins
4/4/2008 7:40:55 PM
Rudy,

Interesting interface (IEquatable); not seen that one before.
Will let you know if this works for me.

Thanks.


[quoted text, click to view]

Barry Kelly
4/5/2008 2:10:45 AM
[quoted text, click to view]

The normal pattern for comparing values of a generic type is to use
Comparer<T>.Default (if you need ordering) or
EqualityComparer<T>.Default (if you need equality and hashing).

EqualityComparer<T>.Default delegates to an IEquatable<T> interface if
it exists, or fall back to the Object.Equals override, if any.

Then, if you deal with some T where you want to customize behaviour
(strings come to mind - do you want case-sensitive versus insensitive
behaviour?), you create an overloaded constructor which takes an
IEqualityComparer<T> instance, and pass EqualityComparer<T>.Default in
the other overload. All comparisons should be done through the cached
interface value.

For the concrete case of strings, you can then use
StringComparer.Ordinal, StringComparer.InvariantCultureIgnoreCase, as
the argument etc.

-- Barry

--
Martin Robins
4/5/2008 3:23:12 PM
Barry,

Thanks; that seems to have done the trick (in as much as it is providing the
correct results).

Martin.

[quoted text, click to view]

Martin Robins
4/5/2008 3:36:09 PM
Barry,

My last message sounded really bad; sorry! Your suggestions have provided
the answer I was looking for. I particularly liked the IEqualityComparer
suggestion and this (along with the overriden constructor) is the one that I
am going with.

Martin.

[quoted text, click to view]

AddThis Social Bookmark Button