473,400 Members | 2,145 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,400 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 1664
> 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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Hung Jung Lu | last post by:
Hi, I just downloaded rotor and gyro and am playing a bit with generics. I enclose a sample program. My question is, according to the language spec...
8
by: Leicester B. Ford Jr. | last post by:
I have come across a problem using generics. I want to create a Factory type that will build classes for me. Code snippet below... static public class Product<T> where T : new() { static...
4
by: Michael Sparks | last post by:
I started writing some code with the 2.0 beta compiler, and found out quickly that specialization is not supported with generics. For example, I want to do something like this: class number...
3
by: Tom Jastrzebski | last post by:
Hello everybody, Here is another problem with generics I come across. Let's say I want to implement a structure performing some operations on some numeric type. I can not than just return...
3
by: Marshal | last post by:
/////////////////////////////////////////////////////////////////////////////////////////////// /// CONSTRAINTS ON GENERICS //////////////////////////////////////////////////// public class...
23
by: Luc Vaillant | last post by:
I need to initialise a typed parameter depending of its type in a generic class. I have tried to use the C++ template form as follow, but it doesn't work. It seems to be a limitation of generics...
8
by: Kris Jennings | last post by:
Hi, I am trying to create a new generic class and am having trouble casting a generic type to a specific type. For example, public class MyClass<Twhere T : MyItemClass, new() { public...
8
by: Gary Brown | last post by:
Hi, When I do the following public class IAmAGeneric<T> { ... public T AMember (T a, T b) { return a + b; }; }
2
by: =?Utf-8?B?QnJhdmVzQ2hhcm0=?= | last post by:
I am trying to convert a class I have to generics and I can't seem to find any possible why to implement it. I'm beginning to think I'm doing something I shouldn't or I hit generics limitation. ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.