|
-
December 10th, 2008, 04:42 PM
#1
Enhancing Looping With Enumerators
Before using enumerators I would have have an exposed data structures and loops like this:
Code:
' Exposed data structures
Public Blocks As New SortedList(Of Integer, Block)
Public RedBlocks As New SortedList(Of Integer, Block)
Public BlueBlocks As New SortedList(Of Integer, Block)
' Loops
For Each blockKVP As KeyValuePair(Of Integer, Block) In Blocks
Dim block As Block = blockKVP.Value
...
Next
For Each blockKVP As KeyValuePair(Of Integer, Block) In BlueBlocks
Dim block As Block = blockKVP.Value
...
Next
Whenever code added/removed blocks to the list the code had to make sure to add/remove from each list. This of course is error prone. Also, if I wanted to maintain another list of blocks in a different color I'd have to modify each block of code that added/removed from the lists.
So I created enumerator classes to encapsulate all this and to protect the data structures. It also made the loop syntax simpler and easier to read.
Code:
' Enumerators
Public Class BlockEnumerator
Implements IEnumerator(Of Block)
...
End Class
Public Class RedBlockEnumator
Implements IEnumerator(Of Block)
....
End Class
Public Class BlockList
Implements IEnumerable(Of Block)
...
End Class
Public Class RedBlockList
Implements IEnumerable(Of Block)
...
End Class
' Protected data structures
Private _Blocks As New SortedList(of integer, Block)
Public Blocks As New BlockList(_Blocks)
Public RedBlocks As New BlockList(_Blocks)
' Simple loops
For Each block In Blocks
...
Next
For Each block In RedBlocks
...
Next
Now my question. I would like to only have one public list and to select the subset of blocks in the looping syntax. I have few thoughts what the syntax might be but I don't know what class/data structures I need in order to do this.
Code Examples
Code:
' Protected data structures
Private _Blocks As New SortedList(of integer, Block)
Public Blocks As New BlockList(_Blocks)
' Loops through all blocks
For Each block In Blocks
...
Next
For Each block In Blocks.AllBlocks
...
Next
For Each block In Blocks(BlockColor.AllColors)
...
Next
' Loops through red blocks
For Each block In Blocks.RedBlocks
...
Next
For Each block In Blocks(BlockColor.RedBlocks)
...
Next
Well, does anyone have any suggestions or know if this is even possible?
Thanks,
Last edited by Scott.Macmaster; December 10th, 2008 at 04:45 PM.
-
December 10th, 2008, 04:46 PM
#2
Re: Enhancing Looping With Enumerators
I would create a SINGLE class that hadd "All" the blocks, then expose enumerators that only returned the ones which met the requirements.
NO multiple collections to maintain, smaller, faster, less error prone, easier to use....whats not to like?
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
December 11th, 2008, 06:59 AM
#3
Re: Enhancing Looping With Enumerators
 Originally Posted by Scott.Macmaster
Before using enumerators I would have have an exposed data structures and loops like this:
Code:
' Loops
For Each blockKVP As KeyValuePair(Of Integer, Block) In Blocks
Dim block As Block = blockKVP.Value
...
Next
Whenever code added/removed blocks to the list the code had to make sure to add/remove from each list. This of course is error prone. Also, if I wanted to maintain another list of blocks in a different color I'd have to modify each block of code that added/removed from the lists.
try:
Code:
' Loops
For Each blockKVP As KeyValuePair(Of Integer, Block) In Blocks.Clone
Dim block As Block = blockKVP.Value
...
Next
That way, yo would iterate on each object on the original SortedList, at the cost of duplicating your data structure before the For...Next. You can delete the same objects in the KeyValuePair, without ruining the logic under you For..Each...Next
Last edited by Marraco; December 11th, 2008 at 07:02 AM.
[Vb.NET 2008 (ex Express)]
-
December 11th, 2008, 08:21 AM
#4
Re: Enhancing Looping With Enumerators
Clonig the list usually has a bigger performance hit than just using a good pattern for handling addition/deletion. This can be implemented at the collection class level. It is also much easier to make thread safe by localizing all of the locking.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
December 11th, 2008, 10:23 AM
#5
Re: Enhancing Looping With Enumerators
Well, that's what I want to do, have everything in one class. I did some more thinking and found a solution. For some reason it didn't initial occur to me I could have a function in an enumerable class that returns an object of a different enumerable class.
This'll work perfectly for my block example. However, the project I'm actually working on involves the list ordered in different ways so I'll still need to manage multiple lists. However, it'll all be in one class and the enumerable objects returned by the functions in the primary enumerable object won't have add/remove functions so my data structures will be completely protected.
Code:
' Enumerators
Public Class BlocksByIdEnumerator
Implements IEnumerator(Of Block)
...
End Class
Public Class BlocksByNameEnumerator
Implements IEnumerator(Of Student)
...
End Class
' Enumerable classes
Public Class BlocksList
Implements IEnumerable(Of Block)
Private Blocks As New SortedList(of Integer, Block)
Private BlocksByName As New SortedList(of String, Block)
Public Functions ByName() As BlocksByNameList
Return New BlocksByNameList(BlocksByName)
End Function
...
End Class
Public Class BlocksByNameList
Implements IEnumerable(Of Block)
Private Blocks As SortedList(Of String, Block)
...
End Class
' Fully protected data structure
Public blocks As BlocksList
' Looping through blocks
For Each block In blocks
...
Next
' Loop through blocks in a different order
For Each block In blocks.ByName
...
Next
Well, I don't think this can be improved anymore.
Thanks,
-
December 11th, 2008, 10:36 AM
#6
Re: Enhancing Looping With Enumerators
Scott, since you posted abbriviated code, I can not be 100% certain, but it still looks as if there is a postential for error.
1) Create BlockList
2) Get Local Reference to BlockList.ByName
3) Remove item from Local Reference (of type BlocksByNameList)
Will the original BlockList properly reflect the change?
Also what happens if the caller tries "new BlocksByNameList" directly?
It seems that this implementation does NOT optimally meet the goal of "Make classes as DIFFICULT as possible to use INCORRECTLY" - Scott Meyers....
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
December 11th, 2008, 10:50 AM
#7
Re: Enhancing Looping With Enumerators
I had said, "and the enumerable objects returned by the functions in the primary enumerable object won't have add/remove functions so my data structures will be completely protected"
Without a add/remove functions you can't modify the internal data structure with the local reference returned by BlockList.ByName.
I only have one constructor for BlocksByNameList
Code:
Public Sub New(blocksByName As SortedList(As String, Block))
Blocks = blocksByName
End Sub
So you can't initialize a BlocksByName object manually with the sortedlist inside of Blocks since there isn't a way to get a reference to it. Not that it would matter since it doesn't have add/remove functions. You could initialize it with your own sortedlist but since it doesn't have add/remove functions that would be pointless.
If you have thoughts on how my code could by misused I'd like to know.
Thanks,
-
December 11th, 2008, 07:21 PM
#8
Re: Enhancing Looping With Enumerators
Post it all. Attach it as a file if it is too big to paste.
-
December 11th, 2008, 10:32 PM
#9
Re: Enhancing Looping With Enumerators
 Originally Posted by Scott.Macmaster
I If you have thoughts on how my code could by misused I'd like to know.
I confess that I was looking much more ad the code, than the text. It seems you have most of the major bases covered, with the possible of some unnecessary object lifetime (this could only be confirmed with a fully compilable piece of code that could be carefully analyzed with a proper profiler.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|