Would you use a custom enumerator?
-
I have a bunch of different structs that implement
IMyType
. I also have some more advanced structs that are essentially containers for x number ofIMyType
instances (they are not lists). They need to be iterated so I am implementingIEnumerable<IMyType>
. At the moment I have made a custom enumerator that has aparams IMyType[] myTypes
parameter in the contructor and using this type of code in the IEnumerable structs:public IEnumerator<IMyType> GetEnumerator()
{
return new MyTypeEnumerator(
new IMyType[] {
new MyType(...),
new MyTypeOther(...) });
}This works fine but I've been considering getting rid of the
MyTypeEnumerator
and using this instead:public IEnumerator<IMyType> GetEnumerator()
{
IEnumerable<IMyType> collection = new IMyType[] {
new MyType(...),
new MyTypeOther(...) };
return collection.GetEnumerator();
}Obviously both work just fine and are pretty much identical. Which would you prefer? Edit: Alternatively, I could just use
return new MyTypeEnumerator(this);
and let theMyTypeEnumerator
take care of it. I don't like that idea - ignoreDave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn) -
I have a bunch of different structs that implement
IMyType
. I also have some more advanced structs that are essentially containers for x number ofIMyType
instances (they are not lists). They need to be iterated so I am implementingIEnumerable<IMyType>
. At the moment I have made a custom enumerator that has aparams IMyType[] myTypes
parameter in the contructor and using this type of code in the IEnumerable structs:public IEnumerator<IMyType> GetEnumerator()
{
return new MyTypeEnumerator(
new IMyType[] {
new MyType(...),
new MyTypeOther(...) });
}This works fine but I've been considering getting rid of the
MyTypeEnumerator
and using this instead:public IEnumerator<IMyType> GetEnumerator()
{
IEnumerable<IMyType> collection = new IMyType[] {
new MyType(...),
new MyTypeOther(...) };
return collection.GetEnumerator();
}Obviously both work just fine and are pretty much identical. Which would you prefer? Edit: Alternatively, I could just use
return new MyTypeEnumerator(this);
and let theMyTypeEnumerator
take care of it. I don't like that idea - ignoreDave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)You'd normally only create a custom enumerator if you want to be able to enumerate the (virtual) collection without holding the whole list in memory all at once. So I don't quite understand the purpose of your implementation. If you can define a list form for your object, why not just expose that?
public IList<IMyType> Items {
get {
IList<IMyType> list = new List<IMyType>();
list.Add(new MyType(...));
list.Add(new MyTypeOther(...));
return list;
}
}public IEnumerator<IMyType> GetEnumerator() { return Items.GetEnumerator(); }
Actually you don't need to implement IEnumerable at all if you do that, you can put the List property on the interface and users can do foreach(IMyType item in myObject.Items) instead of foreach(IMyType item in myObject).
-
You'd normally only create a custom enumerator if you want to be able to enumerate the (virtual) collection without holding the whole list in memory all at once. So I don't quite understand the purpose of your implementation. If you can define a list form for your object, why not just expose that?
public IList<IMyType> Items {
get {
IList<IMyType> list = new List<IMyType>();
list.Add(new MyType(...));
list.Add(new MyTypeOther(...));
return list;
}
}public IEnumerator<IMyType> GetEnumerator() { return Items.GetEnumerator(); }
Actually you don't need to implement IEnumerable at all if you do that, you can put the List property on the interface and users can do foreach(IMyType item in myObject.Items) instead of foreach(IMyType item in myObject).
There is another class that has a method:
public void Send(IEnumerable<IMyType> collection)
{
foreach(IMyType myType in collection)
{
// .....
}
}This is the only place the IEnumerable is used (no need for any sort of list at all), so that leaves the second method as the prefered, essentially what your list is doing but without the list.
Dave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn) -
I have a bunch of different structs that implement
IMyType
. I also have some more advanced structs that are essentially containers for x number ofIMyType
instances (they are not lists). They need to be iterated so I am implementingIEnumerable<IMyType>
. At the moment I have made a custom enumerator that has aparams IMyType[] myTypes
parameter in the contructor and using this type of code in the IEnumerable structs:public IEnumerator<IMyType> GetEnumerator()
{
return new MyTypeEnumerator(
new IMyType[] {
new MyType(...),
new MyTypeOther(...) });
}This works fine but I've been considering getting rid of the
MyTypeEnumerator
and using this instead:public IEnumerator<IMyType> GetEnumerator()
{
IEnumerable<IMyType> collection = new IMyType[] {
new MyType(...),
new MyTypeOther(...) };
return collection.GetEnumerator();
}Obviously both work just fine and are pretty much identical. Which would you prefer? Edit: Alternatively, I could just use
return new MyTypeEnumerator(this);
and let theMyTypeEnumerator
take care of it. I don't like that idea - ignoreDave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Another alternative to consider:
public IEnumerator GetEnumerator()
{
yield return new MyType(...);
yield return new MyTypeOther(...);
...
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
There is another class that has a method:
public void Send(IEnumerable<IMyType> collection)
{
foreach(IMyType myType in collection)
{
// .....
}
}This is the only place the IEnumerable is used (no need for any sort of list at all), so that leaves the second method as the prefered, essentially what your list is doing but without the list.
Dave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)But the point is you are creating the list anyway (well, an array to be precise, but it's pretty much the same thing). However, implementing only IEnumerable and not IList (or exposing a list) implies that the enumeration can be run without the whole thing being in memory all at once. It would be cleaner to expose the list and to pass that to Send (i.e. instead of calling Send(myObject), call Send(myObject.Items), to my mind.
-
Another alternative to consider:
public IEnumerator GetEnumerator()
{
yield return new MyType(...);
yield return new MyTypeOther(...);
...
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Good thinking, much better creating the new
IMyType
s as needed. 5d :-DDave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn) -
I have a bunch of different structs that implement
IMyType
. I also have some more advanced structs that are essentially containers for x number ofIMyType
instances (they are not lists). They need to be iterated so I am implementingIEnumerable<IMyType>
. At the moment I have made a custom enumerator that has aparams IMyType[] myTypes
parameter in the contructor and using this type of code in the IEnumerable structs:public IEnumerator<IMyType> GetEnumerator()
{
return new MyTypeEnumerator(
new IMyType[] {
new MyType(...),
new MyTypeOther(...) });
}This works fine but I've been considering getting rid of the
MyTypeEnumerator
and using this instead:public IEnumerator<IMyType> GetEnumerator()
{
IEnumerable<IMyType> collection = new IMyType[] {
new MyType(...),
new MyTypeOther(...) };
return collection.GetEnumerator();
}Obviously both work just fine and are pretty much identical. Which would you prefer? Edit: Alternatively, I could just use
return new MyTypeEnumerator(this);
and let theMyTypeEnumerator
take care of it. I don't like that idea - ignoreDave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)As was said earlier, there is not much reason to create a custom enumerator these days. The reason for an enumerator is to be able to use the ForEach loop. The
Yield
statement. Then there is also LINQ, Not sure why you are even bothering with an Enumerator given the alternatives avaialable. -
As was said earlier, there is not much reason to create a custom enumerator these days. The reason for an enumerator is to be able to use the ForEach loop. The
Yield
statement. Then there is also LINQ, Not sure why you are even bothering with an Enumerator given the alternatives avaialable.Clifford Nelson wrote:
there is not much reason to create a custom enumerator these days
That's why I asked, it felt somewhat unnecessary.
Clifford Nelson wrote:
Not sure why you are even bothering with an Enumerator given the alternatives avaialable
There are many types in the library that are responsible for creating multiple instances of the interface
IMyType
(the quantity and implementation differs by the type) when required, and all these types need to be able to be passed to one common method so it can iterate over the interface instances -IEnumerable<IMyType>
fits this scenario/concept perfectly, what is was designed for IMO.Dave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn) -
But the point is you are creating the list anyway (well, an array to be precise, but it's pretty much the same thing). However, implementing only IEnumerable and not IList (or exposing a list) implies that the enumeration can be run without the whole thing being in memory all at once. It would be cleaner to expose the list and to pass that to Send (i.e. instead of calling Send(myObject), call Send(myObject.Items), to my mind.
I see where you're coming from. Richard's solution below is the best for this particular situation I think as the array doesn't actually need to be in memory all at once. I can simply create the instances as required using
yield return
directly. Thanks for your input though, it has helped clarify some of my thinking in regards to iterators and foreach which will be helpful in future, and encouraged me to dig deeper into the whole thing that I previously just took for granted :thumbsup:Dave
Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)