471,338 Members | 1,257 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,338 software developers and data experts.

Generics limitation...

I try to compare to values of generic value type T in a generic class as
follow:

public class C<T> where T : struct
{
private T value1;
private T value2;

C(T value1, T value2)
{
this.value1 = value1;
this.value2 = value2;
}

public void SomeMethod()
{
if (value1 != value2)
DoSomething();
}
}

and I got the following message at compile time :

"Operator '!=' cannot be applied to operands of type 'T' and 'T'"

Ok, I can use the following code :

if (value1.Equals(value2) == false)
DoSomething();

but doing so, I'm loosing all the advantage of generics
==> value1 and value2 are boxed before comparison occurs...

It was already the case for variable initialisation, I need to cast a value
to Object before it can be cast back to T (see : 12/29/2005 post "Generics
limitation on .Net") :

value1 = (T)(Object)Int32.MinValue;

since it was used once in my class, I didn't care about extra
boxing/unboxing operation.

But value1 vs value2 comparison occurs in a loop in real situation (I mean
in my real program) :

for (Int32 i = value1.Length; i-- != 0; i++)
{
if (value1[i] != value2[i])
DoSomething();
}

The question is : Does generics really usefull in such sitautions ?

Dec 29 '05 #1
13 1584
> I try to compare to values of generic value type T in a generic class as
follow:
You should read:

I try to compare two values of generic value type T in a generic class as
follow:

;-)
"Luc Vaillant" wrote:
I try to compare to values of generic value type T in a generic class as
follow:

public class C<T> where T : struct
{
private T value1;
private T value2;

C(T value1, T value2)
{
this.value1 = value1;
this.value2 = value2;
}

public void SomeMethod()
{
if (value1 != value2)
DoSomething();
}
}

and I got the following message at compile time :

"Operator '!=' cannot be applied to operands of type 'T' and 'T'"

Ok, I can use the following code :

if (value1.Equals(value2) == false)
DoSomething();

but doing so, I'm loosing all the advantage of generics
==> value1 and value2 are boxed before comparison occurs...

It was already the case for variable initialisation, I need to cast a value
to Object before it can be cast back to T (see : 12/29/2005 post "Generics
limitation on .Net") :

value1 = (T)(Object)Int32.MinValue;

since it was used once in my class, I didn't care about extra
boxing/unboxing operation.

But value1 vs value2 comparison occurs in a loop in real situation (I mean
in my real program) :

for (Int32 i = value1.Length; i-- != 0; i++)
{
if (value1[i] != value2[i])
DoSomething();
}

The question is : Does generics really usefull in such sitautions ?

Dec 29 '05 #2
Luc,

How are you losing the advantage of generics? Generics doesn't lift the
type operators from the type. In other words, if you overload the ==
operator (or != operator in this case), that is NOT visible to your generic
class.

In order to get around it, you will have to create an interface which
exposes the operations, and performs them (instead of using == or !=).
Either that, or you assign a type to the class internally that will handle
the operations based on the type.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Luc Vaillant" <Lu*********@discussions.microsoft.com> wrote in message
news:88**********************************@microsof t.com...
I try to compare to values of generic value type T in a generic class as
follow:

public class C<T> where T : struct
{
private T value1;
private T value2;

C(T value1, T value2)
{
this.value1 = value1;
this.value2 = value2;
}

public void SomeMethod()
{
if (value1 != value2)
DoSomething();
}
}

and I got the following message at compile time :

"Operator '!=' cannot be applied to operands of type 'T' and 'T'"

Ok, I can use the following code :

if (value1.Equals(value2) == false)
DoSomething();

but doing so, I'm loosing all the advantage of generics
==> value1 and value2 are boxed before comparison occurs...

It was already the case for variable initialisation, I need to cast a
value
to Object before it can be cast back to T (see : 12/29/2005 post "Generics
limitation on .Net") :

value1 = (T)(Object)Int32.MinValue;

since it was used once in my class, I didn't care about extra
boxing/unboxing operation.

But value1 vs value2 comparison occurs in a loop in real situation (I mean
in my real program) :

for (Int32 i = value1.Length; i-- != 0; i++)
{
if (value1[i] != value2[i])
DoSomething();
}

The question is : Does generics really usefull in such sitautions ?

Dec 29 '05 #3
"Luc Vaillant" <Lu*********@discussions.microsoft.com> a écrit dans le
message de news: 88**********************************@microsoft.com...

|I try to compare to values of generic value type T in a generic class as
| follow:
|
| public class C<T> where T : struct
| {
| private T value1;
| private T value2;
|
| C(T value1, T value2)
| {
| this.value1 = value1;
| this.value2 = value2;
| }
|
| public void SomeMethod()
| {
| if (value1 != value2)
| DoSomething();
| }
| }
|
| and I got the following message at compile time :
|
| "Operator '!=' cannot be applied to operands of type 'T' and 'T'"

You cannot expect T to support the == or != operators because some types may
not have overloaded them. If you are wanting to compare two Ts in the
generic class then you need to use Equals(...)

However, if you need to compare two instances of your generic class then you
nee to supply operator overloads like this :

public class C<T> where T : struct
{
private T value;

public override bool Equals(object obj)
{
return value.Equals(((C<T>) obj).value);
}

public override int GetHashCode()
{
return value.GetHashCode();
}

public static bool operator ==(C<T> lhs, C<T> rhs)
{
return lhs.value.Equals(rhs.value);
}

public static bool operator !=(C<T> lhs, C<T> rhs)
{
return ! lhs.value.Equals(rhs.value);
}
}

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Dec 29 '05 #4
Sorry, but I don't anderstand... any example ?
"Nicholas Paldino [.NET/C# MVP]" wrote:
Luc,

How are you losing the advantage of generics? Generics doesn't lift the
type operators from the type. In other words, if you overload the ==
operator (or != operator in this case), that is NOT visible to your generic
class.

In order to get around it, you will have to create an interface which
exposes the operations, and performs them (instead of using == or !=).
Either that, or you assign a type to the class internally that will handle
the operations based on the type.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Luc Vaillant" <Lu*********@discussions.microsoft.com> wrote in message
news:88**********************************@microsof t.com...
I try to compare to values of generic value type T in a generic class as
follow:

public class C<T> where T : struct
{
private T value1;
private T value2;

C(T value1, T value2)
{
this.value1 = value1;
this.value2 = value2;
}

public void SomeMethod()
{
if (value1 != value2)
DoSomething();
}
}

and I got the following message at compile time :

"Operator '!=' cannot be applied to operands of type 'T' and 'T'"

Ok, I can use the following code :

if (value1.Equals(value2) == false)
DoSomething();

but doing so, I'm loosing all the advantage of generics
==> value1 and value2 are boxed before comparison occurs...

It was already the case for variable initialisation, I need to cast a
value
to Object before it can be cast back to T (see : 12/29/2005 post "Generics
limitation on .Net") :

value1 = (T)(Object)Int32.MinValue;

since it was used once in my class, I didn't care about extra
boxing/unboxing operation.

But value1 vs value2 comparison occurs in a loop in real situation (I mean
in my real program) :

for (Int32 i = value1.Length; i-- != 0; i++)
{
if (value1[i] != value2[i])
DoSomething();
}

The question is : Does generics really usefull in such sitautions ?


Dec 29 '05 #5
> You cannot expect T to support the == or != operators because some types may
not have overloaded them. If you are wanting to compare two Ts in the
generic class then you need to use Equals(...)
So, I'm loosing (Speed) advantage of generics because of boxing operations...

I explain :

If using the two class definition bellow :

A<int> classA = new A<int>();
B classB = new B();

B.SomeComparison(12345) should be faster than A.SomeComparison(12345)
because boxing operations are already done.
Of course, class initialization is slower for class B because values are
boxed into ArrayList, but this is done only once.

public class A<T> where T : struct
{
private List<T> myList;

public A()
{
// Initializing myList...
}

public void SomeComparison(T aValue)
{
Object boxedValue = (Object)aValue;

for (int i = myList.Count; i-- != 0; )
{
if (myList[i].Equals(boxedValue))
DoSomething();
}
}

public class B
{
private ArrayList myList;

public B()
{
// Initializing myList...
}

public void SomeComparison(int aValue)
{
Object boxedValue = (Object)aValue;

for (int i = myList.Count; i-- != 0; )
{
if (myList[i].Equals(boxedValue))
DoSomething();
}
}


"Joanna Carter [TeamB]" wrote:
"Luc Vaillant" <Lu*********@discussions.microsoft.com> a écrit dans le
message de news: 88**********************************@microsoft.com...

|I try to compare to values of generic value type T in a generic class as
| follow:
|
| public class C<T> where T : struct
| {
| private T value1;
| private T value2;
|
| C(T value1, T value2)
| {
| this.value1 = value1;
| this.value2 = value2;
| }
|
| public void SomeMethod()
| {
| if (value1 != value2)
| DoSomething();
| }
| }
|
| and I got the following message at compile time :
|
| "Operator '!=' cannot be applied to operands of type 'T' and 'T'"

You cannot expect T to support the == or != operators because some types may
not have overloaded them. If you are wanting to compare two Ts in the
generic class then you need to use Equals(...)

However, if you need to compare two instances of your generic class then you
nee to supply operator overloads like this :

public class C<T> where T : struct
{
private T value;

public override bool Equals(object obj)
{
return value.Equals(((C<T>) obj).value);
}

public override int GetHashCode()
{
return value.GetHashCode();
}

public static bool operator ==(C<T> lhs, C<T> rhs)
{
return lhs.value.Equals(rhs.value);
}

public static bool operator !=(C<T> lhs, C<T> rhs)
{
return ! lhs.value.Equals(rhs.value);
}
}

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer

Dec 29 '05 #6
Luc Vaillant wrote:
I try to compare to values of generic value type T in a generic class
as follow:

public class C<T> where T : struct
{
private T value1;
private T value2;

C(T value1, T value2)
{
this.value1 = value1;
this.value2 = value2;
}

public void SomeMethod()
{
if (value1 != value2)
DoSomething();
}
}

and I got the following message at compile time :

"Operator '!=' cannot be applied to operands of type 'T' and 'T'"

Ok, I can use the following code :

if (value1.Equals(value2) == false)
DoSomething();

but doing so, I'm loosing all the advantage of generics
==> value1 and value2 are boxed before comparison occurs...

It was already the case for variable initialisation, I need to cast a
value to Object before it can be cast back to T (see : 12/29/2005
post "Generics limitation on .Net") :

value1 = (T)(Object)Int32.MinValue;

since it was used once in my class, I didn't care about extra
boxing/unboxing operation.

But value1 vs value2 comparison occurs in a loop in real situation (I
mean in my real program) :

for (Int32 i = value1.Length; i-- != 0; i++)
{
if (value1[i] != value2[i])
DoSomething();
}

The question is : Does generics really usefull in such sitautions ?


answer: no.

MS didn't implement a filter spec for static defined operator
overloads so you can specify them in a where clause for the generic
type. This thus means the compiler doesn't know for sure the generic
type implements the operators used in the code.

It's unfortunate, but not solvable, you have to work around it for now.

Frans

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Dec 30 '05 #7
Hi Frans,

I found a solution to my problem:

class MyComp : IComparer<short>, IComparer<int>
{
public int Compare(int x, int y) { return x - y; }
public int Compare(short x, short y) { return x - y; }
}

class GenClass<T, I> where I : IComparer<T>, new()
{
private IComparer<T> comparer = new I();

public void SomeMethod(T value1, T value2)
{
if (comparer.Compare(value1, value2) == 0)
DoSomething();
}
}

Thanks
Luc

"Frans Bouma [C# MVP]" wrote:
Luc Vaillant wrote:
I try to compare to values of generic value type T in a generic class
as follow:

public class C<T> where T : struct
{
private T value1;
private T value2;

C(T value1, T value2)
{
this.value1 = value1;
this.value2 = value2;
}

public void SomeMethod()
{
if (value1 != value2)
DoSomething();
}
}

and I got the following message at compile time :

"Operator '!=' cannot be applied to operands of type 'T' and 'T'"

Ok, I can use the following code :

if (value1.Equals(value2) == false)
DoSomething();

but doing so, I'm loosing all the advantage of generics
==> value1 and value2 are boxed before comparison occurs...

It was already the case for variable initialisation, I need to cast a
value to Object before it can be cast back to T (see : 12/29/2005
post "Generics limitation on .Net") :

value1 = (T)(Object)Int32.MinValue;

since it was used once in my class, I didn't care about extra
boxing/unboxing operation.

But value1 vs value2 comparison occurs in a loop in real situation (I
mean in my real program) :

for (Int32 i = value1.Length; i-- != 0; i++)
{
if (value1[i] != value2[i])
DoSomething();
}

The question is : Does generics really usefull in such sitautions ?


answer: no.

MS didn't implement a filter spec for static defined operator
overloads so you can specify them in a where clause for the generic
type. This thus means the compiler doesn't know for sure the generic
type implements the operators used in the code.

It's unfortunate, but not solvable, you have to work around it for now.

Frans

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Dec 30 '05 #8
"Luc Vaillant" <Lu*********@discussions.microsoft.com> a écrit dans le
message de news: 8A**********************************@microsoft.com...

| I found a solution to my problem:
|
| class MyComp : IComparer<short>, IComparer<int>
| {
| public int Compare(int x, int y) { return x - y; }
| public int Compare(short x, short y) { return x - y; }
| }
|
| class GenClass<T, I> where I : IComparer<T>, new()
| {
| private IComparer<T> comparer = new I();
|
| public void SomeMethod(T value1, T value2)
| {
| if (comparer.Compare(value1, value2) == 0)
| DoSomething();
| }
| }

Well, I was obviously on the right track suggesting IComparable<T>; given
that yours is not the only question I was thinking about, at least that may
have pushed you in the direction of using IComparer<T> :-)

If you think the advice is worth taking :-), but for others benefit anyway,
you might like to take care if you wanted to apply this to floating point
numbers as they can throw unpredictable results when checking for equality
of calculated values compared with constant values.

So you see, generics did not have the limitations you thought, you just had
to get inventive and use what was available :-)

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Dec 30 '05 #9
Luc Vaillant <Lu*********@discussions.microsoft.com> wrote:
I found a solution to my problem:

class MyComp : IComparer<short>, IComparer<int>
{
public int Compare(int x, int y) { return x - y; }
public int Compare(short x, short y) { return x - y; }
}

class GenClass<T, I> where I : IComparer<T>, new()
{
private IComparer<T> comparer = new I();

public void SomeMethod(T value1, T value2)
{
if (comparer.Compare(value1, value2) == 0)
DoSomething();
}
}


Do you actually need to provide an IComparer<T>? int and short both
implement IComparable<themselves>. Can't you just use:

class GenClass<T> where T : IComparable<T>,
{
public void SomeMethod(T value1, T value2)
{
if (value1.CompareTo(value2) == 0)
DoSomething();
}
}

I don't believe that involves any boxing - at least, it doesn't seem to
induce any garbage collections in the following program:

using System;

class GenClass<T> where T : IComparable<T>
{
public void SomeMethod(T value1, T value2)
{
if (value1.CompareTo(value2) == 0)
DoSomething();
// object o = value1;
}

void DoSomething()
{
}
}

public class Test
{
static void Main()
{
Console.WriteLine ("Ready?");
Console.ReadLine();
GenClass<int> test = new GenClass<int>();

for (int i=0; i < 10000000; i++)
{
test.SomeMethod (1, 2);
}
Console.WriteLine ("Finished");
Console.ReadLine();
}
}

If you uncomment the commented out line to force boxing each iteration,
you'll see lots of Gen0 collections in PerfMon. With it commented out,
you don't see any (or at least I don't).

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 30 '05 #10
Great, I didn't knew that numeric and string implement IComparable<T> and
IEquatable<T>

Thanks a lot

"Jon Skeet [C# MVP]" wrote:
Luc Vaillant <Lu*********@discussions.microsoft.com> wrote:
I found a solution to my problem:

class MyComp : IComparer<short>, IComparer<int>
{
public int Compare(int x, int y) { return x - y; }
public int Compare(short x, short y) { return x - y; }
}

class GenClass<T, I> where I : IComparer<T>, new()
{
private IComparer<T> comparer = new I();

public void SomeMethod(T value1, T value2)
{
if (comparer.Compare(value1, value2) == 0)
DoSomething();
}
}


Do you actually need to provide an IComparer<T>? int and short both
implement IComparable<themselves>. Can't you just use:

class GenClass<T> where T : IComparable<T>,
{
public void SomeMethod(T value1, T value2)
{
if (value1.CompareTo(value2) == 0)
DoSomething();
}
}

I don't believe that involves any boxing - at least, it doesn't seem to
induce any garbage collections in the following program:

using System;

class GenClass<T> where T : IComparable<T>
{
public void SomeMethod(T value1, T value2)
{
if (value1.CompareTo(value2) == 0)
DoSomething();
// object o = value1;
}

void DoSomething()
{
}
}

public class Test
{
static void Main()
{
Console.WriteLine ("Ready?");
Console.ReadLine();
GenClass<int> test = new GenClass<int>();

for (int i=0; i < 10000000; i++)
{
test.SomeMethod (1, 2);
}
Console.WriteLine ("Finished");
Console.ReadLine();
}
}

If you uncomment the commented out line to force boxing each iteration,
you'll see lots of Gen0 collections in PerfMon. With it commented out,
you don't see any (or at least I don't).

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Dec 30 '05 #11
Luc Vaillant <Lu*********@discussions.microsoft.com> wrote:
Great, I didn't knew that numeric and string implement IComparable<T> and
IEquatable<T>

Thanks a lot


No problem. It's worth noting that I'm only pretty much repeating what
Joanna said though :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 30 '05 #12
"Luc Vaillant" <Lu*********@discussions.microsoft.com> a écrit dans le
message de news: 39**********************************@microsoft.com...

| Great, I didn't knew that numeric and string implement IComparable<T> and
| IEquatable<T>

Wow, neither did I !!

Take a look at the new 2.0 help on types derived from ValueType, it's
astounding what's in there.

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Dec 30 '05 #13
Certainly because the way you wrote it was clear

"Jon Skeet [C# MVP]" wrote:
Luc Vaillant <Lu*********@discussions.microsoft.com> wrote:
Great, I didn't knew that numeric and string implement IComparable<T> and
IEquatable<T>

Thanks a lot


No problem. It's worth noting that I'm only pretty much repeating what
Joanna said though :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Dec 30 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Hung Jung Lu | last post: by
8 posts views Thread by Leicester B. Ford Jr. | last post: by
4 posts views Thread by Michael Sparks | last post: by
3 posts views Thread by Tom Jastrzebski | last post: by
3 posts views Thread by Marshal | last post: by
23 posts views Thread by Luc Vaillant | last post: by
8 posts views Thread by Kris Jennings | last post: by
8 posts views Thread by Gary Brown | last post: by
2 posts views Thread by =?Utf-8?B?QnJhdmVzQ2hhcm0=?= | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.