Generics and comparison (follow on from my previous "Generics and collections" thread)
Generics and comparison (follow on from my previous "Generics and collections" thread)
am 04.04.2008 18:53:12 von Martin Robins
This is a multi-part message in MIME format.
------=_NextPart_000_000C_01C8967C.C0148320
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
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 '==' 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!
Thanks in advance.
------=_NextPart_000_000C_01C8967C.C0148320
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
charset=3Diso-8859-1">
Marc has sorted my problem with the =
collections,=20
however I am now in a new scenario; I am trying to compare a generic =
property=20
value before setting it as shown below ...
size=3D2>
size=3D1>
public
size=3D1> T Value {
=
get=20
{ return
color=3D#0000ff>this
size=3D1>.value; }
=20
set {
=20
if ( this.value =
!=3D
color=3D#0000ff>value ) =
{
=20
this.value =3D
color=3D#0000ff>value;
=20
this.OnValueChanged(
color=3D#2b91af>EventArgs
size=3D2>.Empty);
=
=20
}
}
}
This code produces the
color=3D#ff0000>Operator '==' cannot be applied to operands of =
type 'T' and=20
'T' error at compile time!
I am sure that I am not the only person =
to have=20
tried this, any clues as to the correct work around?
I have tried restricting 'T' to =
IComparable in a=20
where clause and then casting 'this.value' and 'value' to IComparable =
for the=20
comparison - the code then compiles but is this the right answer? It =
feels=20
wrong, but I am quickly learning that my own understanding of generics =
is much=20
lower than I thought it was!
Thanks in advance.
------=_NextPart_000_000C_01C8967C.C0148320--
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 04.04.2008 20:19:24 von Rudy Velthuis
Martin Robins wrote:
> 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 != value ) {
> this.value = value;
> this.OnValueChanged(EventArgs.Empty);
> }
> }
> }
>
> This code produces the Operator '==' cannot be applied to operands of
> type 'T' and 'T' error at compile time!
You'll have to put a constraint on T (where clause), so that it only
applies to instances that implement IEquitable, and then use
IEquitable.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
"RAM /abr./: Rarely Adequate Memory." -- From the Jargon File
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 04.04.2008 20:25:15 von Martin Robins
This is a multi-part message in MIME format.
------=_NextPart_000_005E_01C89689.9C2203E0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
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 == null ? value =
!=3D null : !this.value.Equals(value) )" but I am still open to a better =
way if it exists ...
Martin.
"Martin Robins" 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 '==' 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!
Thanks in advance.
------=_NextPart_000_005E_01C89689.9C2203E0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
charset=3Diso-8859-1">
Though it compiles, the original =
IComparable idea=20
did not work; the comparisons would often return incorrect =
results.
I have resolved it for now using "
color=3D#0000ff>if ( this.value =
==
color=3D#0000ff>null ? value !=3D =
color=3D#0000ff>null : !
color=3D#0000ff>this.value.Equals(
color=3D#0000ff>value) )" but I am still open to a better way if =
it exists=20
....
Martin.
style=3D"PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; =
BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
"Martin Robins" <martin at orpheus-solutions dot co dot uk> =
wrote=20
in message
=
href=3D"news:ujRpfRnlIHA.536@TK2MSFTNGP06.phx.gbl">news:ujRp fRnlIHA.536@T=
K2MSFTNGP06.phx.gbl...
Marc has sorted my problem with the =
collections,=20
however I am now in a new scenario; I am trying to compare a generic =
property=20
value before setting it as shown below ...
size=3D2>
size=3D1>
=
public
size=3D1> T Value {
=
=20
get { return
color=3D#0000ff>this.value; =
}
=
=20
set {
=
=20
if ( this.value =
!=3D
color=3D#0000ff>value ) =
{
=
=20
this.value =3D
color=3D#0000ff>value
size=3D2>;
=
=20
this.OnValueChanged(
color=3D#2b91af>EventArgs
size=3D2>.Empty);
=
=20
}
=
}
}
This code produces the
color=3D#ff0000>Operator '==' cannot be applied to operands of =
type 'T' and=20
'T' error at compile time!
I am sure that I am not the only =
person to have=20
tried this, any clues as to the correct work around?
I have tried restricting 'T' to =
IComparable in a=20
where clause and then casting 'this.value' and 'value' to IComparable =
for the=20
comparison - the code then compiles but is this the right answer? It =
feels=20
wrong, but I am quickly learning that my own understanding of generics =
is much=20
lower than I thought it was!
Thanks in advance.
size=3D2>
------=_NextPart_000_005E_01C89689.9C2203E0--
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 04.04.2008 20:40:55 von Martin Robins
Rudy,
Interesting interface (IEquatable); not seen that one before.
Will let you know if this works for me.
Thanks.
"Rudy Velthuis" wrote in message
news:xn0fojkh62vieo1003@news.microsoft.com...
> Martin Robins wrote:
>
>> 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 != value ) {
>> this.value = value;
>> this.OnValueChanged(EventArgs.Empty);
>> }
>> }
>> }
>>
>> This code produces the Operator '==' cannot be applied to operands of
>> type 'T' and 'T' error at compile time!
>
> You'll have to put a constraint on T (where clause), so that it only
> applies to instances that implement IEquitable, and then use
> IEquitable.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
>
> "RAM /abr./: Rarely Adequate Memory." -- From the Jargon File
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 04.04.2008 21:13:23 von Rudy Velthuis
Martin Robins wrote:
> Though it compiles, the original IComparable idea did not work; the
> comparisons would often return incorrect results.
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,
where it is much more comfortable." -- HG Wells.
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 05.04.2008 03:10:45 von Barry Kelly
"Martin Robins" wrote:
> 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 != value ) {
> this.value = value;
> this.OnValueChanged(EventArgs.Empty);
> }
> }
> }
>
> This code produces the Operator '==' 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?
The normal pattern for comparing values of a generic type is to use
Comparer.Default (if you need ordering) or
EqualityComparer.Default (if you need equality and hashing).
EqualityComparer.Default delegates to an IEquatable 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 instance, and pass EqualityComparer.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
--
http://barrkel.blogspot.com/
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 05.04.2008 16:23:12 von Martin Robins
Barry,
Thanks; that seems to have done the trick (in as much as it is providing the
correct results).
Martin.
"Barry Kelly" wrote in message
news:8ujdv35e4jl1jmbprf6kkppc2dg9vdpc1m@4ax.com...
> "Martin Robins" wrote:
>
>> 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 != value ) {
>> this.value = value;
>> this.OnValueChanged(EventArgs.Empty);
>> }
>> }
>> }
>>
>> This code produces the Operator '==' 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?
>
> The normal pattern for comparing values of a generic type is to use
> Comparer.Default (if you need ordering) or
> EqualityComparer.Default (if you need equality and hashing).
>
> EqualityComparer.Default delegates to an IEquatable 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 instance, and pass EqualityComparer.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
>
> --
> http://barrkel.blogspot.com/
Re: Generics and comparison (follow on from my previous "Generics and collections" thread)
am 05.04.2008 16:36:09 von Martin Robins
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.
"Martin Robins" wrote in message
news:OrggXiylIHA.3636@TK2MSFTNGP02.phx.gbl...
> Barry,
>
> Thanks; that seems to have done the trick (in as much as it is providing
> the correct results).
>
> Martin.
>
> "Barry Kelly" wrote in message
> news:8ujdv35e4jl1jmbprf6kkppc2dg9vdpc1m@4ax.com...
>> "Martin Robins" wrote:
>>
>>> 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 != value ) {
>>> this.value = value;
>>> this.OnValueChanged(EventArgs.Empty);
>>> }
>>> }
>>> }
>>>
>>> This code produces the Operator '==' 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?
>>
>> The normal pattern for comparing values of a generic type is to use
>> Comparer.Default (if you need ordering) or
>> EqualityComparer.Default (if you need equality and hashing).
>>
>> EqualityComparer.Default delegates to an IEquatable 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 instance, and pass EqualityComparer.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
>>
>> --
>> http://barrkel.blogspot.com/
>
>