473,480 Members | 2,277 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Generics collection class that supports foreach ..

I am writing a generic container class which I want to support the
'foreach' statement.

My class looks something like this:

class MyClass<T: CollectionBase
{
//Implementation for MyClass<Tgoes here ...
// ...

//The next method causes compiler warning
IEnumerator GetEnumerator()
{
return (IEnumerator) new MyClassEnumerator<T>(this) ;
}

private class MyClassEnumerator<T>: IEnumerator
{
private int idx;
private MyClass<Tobj ;

//IEnumerator methods implemented here ...
}
}

The warning is that the method 'hides' the GetEnumerator() in
CollectionBase - and the suggestion is that I use the new keyword. What
gives? I mean I understand when the new keywod is used - but this seems
like too much "hand holding" by the compiler - Unless I am reinventing
the wheel here , and I automatically inherit the enumeration
functionality I desire (i.e. use of the foreach statement)
"automagically" - by dint of the fact that I am inheriting from
CollectionBase?
PS: I'm new to C#, but coming from several years C/C++ background.
Feb 17 '07 #1
11 1846
CollectionBase assumes you will be adding items to it's internal List
property. The CollectionBase.GetEnumerator() then iterates across that
list, it does not need any "help" from you to do so. Maybe it is
CollectionBase that you should not be inheriting from. If you are wanting
to implement custom storage of the list, and a custom enumerator, you may
want to try deriving from the generic interfaces instead (such as IList<if
a "list" adequately represents the collection you are creating).

--
Adam Clauss

"Bit Byte" <ro**@your.box.comwrote in message
news:la******************************@bt.com...
>I am writing a generic container class which I want to support the
'foreach' statement.

My class looks something like this:

class MyClass<T: CollectionBase
{
//Implementation for MyClass<Tgoes here ...
// ...

//The next method causes compiler warning
IEnumerator GetEnumerator()
{
return (IEnumerator) new MyClassEnumerator<T>(this) ;
}

private class MyClassEnumerator<T>: IEnumerator
{
private int idx;
private MyClass<Tobj ;

//IEnumerator methods implemented here ...
}
}

The warning is that the method 'hides' the GetEnumerator() in
CollectionBase - and the suggestion is that I use the new keyword. What
gives? I mean I understand when the new keywod is used - but this seems
like too much "hand holding" by the compiler - Unless I am reinventing the
wheel here , and I automatically inherit the enumeration functionality I
desire (i.e. use of the foreach statement) "automagically" - by dint of
the fact that I am inheriting from CollectionBase?
PS: I'm new to C#, but coming from several years C/C++ background.

Feb 17 '07 #2
Bit Byte <ro**@your.box.comwrote:

<snip>
The warning is that the method 'hides' the GetEnumerator() in
CollectionBase - and the suggestion is that I use the new keyword. What
gives? I mean I understand when the new keywod is used - but this seems
like too much "hand holding" by the compiler - Unless I am reinventing
the wheel here , and I automatically inherit the enumeration
functionality I desire (i.e. use of the foreach statement)
"automagically" - by dint of the fact that I am inheriting from
CollectionBase?
The compiler doing some hand-holding is entirely appropriate here -
CollectionBase already implement IEnumerable, so the compiler is
telling you that you're hiding an existing method. It's also
effectively informing you that you're *not* overriding the existing
method, but hiding it. If all of that is really what you want to do,
you should use "new" - but in this case, unless you actually want to
provide a completely different IEnumerator semantics, you just don't
want to write the extra code. Note that if you *do* want to provide
different semantics, you'll get different behaviour depending on how
exactly GetEnumerator is called.

Basically, because member hiding is not something you want to do often,
the compiler wants you to explicitly use the "new" modifier when you do
so, just in case you didn't mean to (as here).

--
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
Feb 17 '07 #3


"Bit Byte" <ro**@your.box.comwrote in message
news:la******************************@bt.com...
>I am writing a generic container class which I want to support the
'foreach' statement.

My class looks something like this:

class MyClass<T: CollectionBase
{
//Implementation for MyClass<Tgoes here ...
// ...

//The next method causes compiler warning
IEnumerator GetEnumerator()
{
return (IEnumerator) new MyClassEnumerator<T>(this) ;
}

private class MyClassEnumerator<T>: IEnumerator
{
private int idx;
private MyClass<Tobj ;

//IEnumerator methods implemented here ...
}
}
You don't need to implement GetEnumerator, the base class does that. If you
want to add a typed enumerator declare that you implement IEnumerable<Tand
implement that explicily.

Like this:

class MyClass<T: CollectionBase, IEnumerable<T>
{

private class MyClassEnumerator : IEnumerator<T>
{
private int idx;
private MyClass<Tobj;

public MyClassEnumerator(MyClass<TmyClass)
{
obj = MyClass;
}

//IEnumerator methods implemented here ...
}

IEnumerator<TIEnumerable<T>.GetEnumerator()
{
return new MyClassEnumerator<T>(this);
}

}

David

Feb 17 '07 #4
(continuing with top posting - to maintain readability)
Hi Adam,

If I understand correctly, what you are saying is that I can use the
'foreach' statement when using my generic collection - WITHOUT having to
explicity implement it (by means of an inner class as I did earlier) -
because CollectionBase already provides this?

So I can write something like this (I know I could easily test this
myself - but I am in the middle of porting accross a huge C++ library ..) :

void FooBar()
{
MyClass<stringcol = new MyClass<String>() ;
col.Add("hello") ;
col.Add("there") ;
col.Add("again") ;

foreach (string s in col)
Console.Write("{0}\n", s) ;

}

Will the code above work (ignoring any typos etc) ?

Adam Clauss wrote:
CollectionBase assumes you will be adding items to it's internal List
property. The CollectionBase.GetEnumerator() then iterates across that
list, it does not need any "help" from you to do so. Maybe it is
CollectionBase that you should not be inheriting from. If you are wanting
to implement custom storage of the list, and a custom enumerator, you may
want to try deriving from the generic interfaces instead (such as IList<if
a "list" adequately represents the collection you are creating).

--
Adam Clauss

"Bit Byte" <ro**@your.box.comwrote in message
news:la******************************@bt.com...
>>I am writing a generic container class which I want to support the
'foreach' statement.

My class looks something like this:

class MyClass<T: CollectionBase
{
//Implementation for MyClass<Tgoes here ...
// ...

//The next method causes compiler warning
IEnumerator GetEnumerator()
{
return (IEnumerator) new MyClassEnumerator<T>(this) ;
}

private class MyClassEnumerator<T>: IEnumerator
{
private int idx;
private MyClass<Tobj ;

//IEnumerator methods implemented here ...
}
}

The warning is that the method 'hides' the GetEnumerator() in
CollectionBase - and the suggestion is that I use the new keyword. What
gives? I mean I understand when the new keywod is used - but this seems
like too much "hand holding" by the compiler - Unless I am reinventing the
wheel here , and I automatically inherit the enumeration functionality I
desire (i.e. use of the foreach statement) "automagically" - by dint of
the fact that I am inheriting from CollectionBase?
PS: I'm new to C#, but coming from several years C/C++ background.


Feb 17 '07 #5
Is it also being hidden because he didn't specify public? Since he didn't
specify it defaults to private right? I come from a C++ background as well
and I'm still learning C#.

just asking,
jim

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Bit Byte <ro**@your.box.comwrote:

<snip>
>The warning is that the method 'hides' the GetEnumerator() in
CollectionBase - and the suggestion is that I use the new keyword. What
gives? I mean I understand when the new keywod is used - but this seems
like too much "hand holding" by the compiler - Unless I am reinventing
the wheel here , and I automatically inherit the enumeration
functionality I desire (i.e. use of the foreach statement)
"automagically" - by dint of the fact that I am inheriting from
CollectionBase?

The compiler doing some hand-holding is entirely appropriate here -
CollectionBase already implement IEnumerable, so the compiler is
telling you that you're hiding an existing method. It's also
effectively informing you that you're *not* overriding the existing
method, but hiding it. If all of that is really what you want to do,
you should use "new" - but in this case, unless you actually want to
provide a completely different IEnumerator semantics, you just don't
want to write the extra code. Note that if you *do* want to provide
different semantics, you'll get different behaviour depending on how
exactly GetEnumerator is called.

Basically, because member hiding is not something you want to do often,
the compiler wants you to explicitly use the "new" modifier when you do
so, just in case you didn't mean to (as here).

--
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

Feb 17 '07 #6
"Bit Byte" <ro**@your.box.comwrote in message
news:Qf******************************@bt.com...
(continuing with top posting - to maintain readability)
My fault on that, I'm really trying to break that old habit, still
occasionally forget :)
If I understand correctly, what you are saying is that I can use the
'foreach' statement when using my generic collection - WITHOUT having to
explicity implement it (by means of an inner class as I did earlier) -
because CollectionBase already provides this?
Correct, CollectionBase already implements a default Enumerator(). Only
reason you would need to provide your own is if you know it is doing
something wrong. And if you DO need to provide your own... I would really
recommend not using CollectionBase (see Jon's discussion about hiding
members using 'new'). That can lead to bad unintended consequences.
So I can write something like this (I know I could easily test this
myself - but I am in the middle of porting accross a huge C++ library ..)
:

void FooBar()
{
MyClass<stringcol = new MyClass<String>() ;
col.Add("hello") ;
col.Add("there") ;
col.Add("again") ;

foreach (string s in col)
Console.Write("{0}\n", s) ;

}

Will the code above work (ignoring any typos etc) ?
I don't see any immediate reason it wouldn't.

I also want to express concern that you are using generics, but using the
non-generic CollectionBase. Despite you doing
MyClass<stringcol = new MyClass<String>() ;

The Add method is simply inherited from CollectionBase, correct? Thus, it
simply takes an object as a parameter, not a string. So this would be
valid, and run successfully:
col.Add(2);

But then when you get down to your foreach() loop, it would throw an
InvalidCastException (I think that's the right one... an exception of some
form anyway) because the integer 2 is not of type string.

You might consider instead inheriting from List<Tand overriding methods as
necessary for whatever custom implementation you are doing. This again,
already implements the enumerator for you, and also provides the type safety
of ensuring only items of the generic type (strings in this example) are
added to the list.

Hope that helps, let me know if you have any other questions.

--
Adam Clauss
Feb 17 '07 #7
"Adam Clauss" <ca*****@gmail.comwrote in message
news:45***********************@roadrunner.com...
"Bit Byte" <ro**@your.box.comwrote in message
news:Qf******************************@bt.com...
>void FooBar()
{
MyClass<stringcol = new MyClass<String>() ;
col.Add("hello") ;
col.Add("there") ;
col.Add("again") ;

foreach (string s in col)
Console.Write("{0}\n", s) ;

}

Will the code above work (ignoring any typos etc) ?

I don't see any immediate reason it wouldn't.

I also want to express concern that you are using generics, but using the
non-generic CollectionBase. Despite you doing
MyClass<stringcol = new MyClass<String>() ;

The Add method is simply inherited from CollectionBase, correct? Thus, it
simply takes an object as a parameter, not a string. So this would be
valid, and run successfully:
col.Add(2);
Correction here - I made a bad assumption. I thought Add was part of
CollectionBase.
The whole discussion of whether or not the built-in enumeration will work
for you depends on your implementation Add. If you are putting them in
CollectionBase's own List, then the built-in enumeration works fine. If you
are not... then you have no need to use CollectionBase :)

--
Adam Clauss
Feb 17 '07 #8
Jim H <ji**@nospam.nospamwrote:
Is it also being hidden because he didn't specify public? Since he didn't
specify it defaults to private right? I come from a C++ background as well
and I'm still learning C#.
It does default to private, but that's got nothing to do with it hiding
the existing method. It's not that the new version is *being* hidden,
it's that it *is* hiding the existing method.

--
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
Feb 17 '07 #9
Adam Clauss <ca*****@gmail.comwrote:
Correction here - I made a bad assumption. I thought Add was part of
CollectionBase.
It is. It explicitly implements IList.Add.

--
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
Feb 17 '07 #10
"Bit Byte" <ro**@your.box.coma écrit dans le message de news:
la******************************@bt.com...

|I am writing a generic container class which I want to support the
| 'foreach' statement.
|
| My class looks something like this:
|
| class MyClass<T: CollectionBase
| {
| //Implementation for MyClass<Tgoes here ...
| // ...

Can I ask why you are not using System.Collections.Generic.List<T? This
already supports IEnumerable and IEnumerable<T>, thus making it suitable for
use with the foreach construct. Or do you want a custom enumerator ?

{
List<Customercustomers = ......

foreach (Customer c in customers)
......

}

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Feb 17 '07 #11
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Adam Clauss <ca*****@gmail.comwrote:
>Correction here - I made a bad assumption. I thought Add was part of
CollectionBase.

It is. It explicitly implements IList.Add.
Alright... I officially need to stop posting here that early in the morning.

--
Adam Clauss
Feb 17 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1772
by: K.K. | last post by:
Consider the following code: >>>>>>>>>>> // Define an empty class public class ZorgleCollection : Dictionary<string, Zorgle> { } // Somewhere outside ZorgleCollection:
4
1620
by: noname | last post by:
I'm learning C# generics recenly. How do i do to write the similar Java function below in C#? void printCollection(Collection<? extends A> c) { for (Object e: c) { System.out.println(e); }} ...
3
1933
by: Marshal | last post by:
/////////////////////////////////////////////////////////////////////////////////////////////// /// CONSTRAINTS ON GENERICS //////////////////////////////////////////////////// public class...
1
6064
by: uttara | last post by:
I have a generic collection which I am using in classes to store a collection of embedded objects. Class Employee: IEntity { Private string mName; Private int mEmployeeID; …. Private...
5
2908
by: anders.forsgren | last post by:
This is a common problem with generics, but I hope someone has found the best way of solving it. I have these classes: "Fruit" which is a baseclass, and "Apple" which is derived. Further I have...
9
5943
by: sloan | last post by:
I'm not the sharpest knife in the drawer, but not a dummy either. I'm looking for a good book which goes over Generics in great detail. and to have as a reference book on my shelf. Personal...
6
1328
by: mopicus | last post by:
hello all, i have two base classes, one inherits from bindinglist<> i need baseobject contains a generic reference to collection that contains it class baseobject<T> : where...
7
5727
by: =?Utf-8?B?Q29kZVJhem9y?= | last post by:
Can someone explain a few things about collections to me. In C# 2 generics, you can create a collection class by inheriting from System.Collections.ObjectModel.Collection. Using this you can...
2
138
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
7048
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
7050
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7091
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6743
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
6966
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
4787
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...
0
4488
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
2999
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
185
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.