'For-Each' Of My Own The .NET Framework provides many new collection classes that you can iterate (for-each) through.But did you know that you can also iterate through values in any of your classes, not just those that use or inherit from collections? This article assumes a basic knowledge of collection classes for the sake of the quick-review at the beginning. One of the coolest things I like about the .NET Framework is the way collections are designed and handled. On the surface, you simply see many types of collections, stored in the System.Collections namespace. In fact, there is another namespace directly under this one called System.Collections.Specialized, which contains even more collection types, including one that mimics the old-fashioned Visual Basic 6.0 collection. What is not completely obvious is how these collections work internally. While this is not a tutorial on .NET collections, it's important to understand the basics of what lies beneath the surface of all these new collection types. Under the Hood of Collections The heart of all the collection classes in the .NET Framework is really a set of interfaces. Which interfaces are implemented and how they are implemented determine the capabilities and behavior of any particular collection class. The two main interfaces used in collection classes are ICollection and IList. ICollection provides the functionality for item counts, enumerating, and synchronization. IList defines the methods and properties that allow the storage of items and all functionality to address that storage (add, remove, etc.). The enumeration capabilities are defined in the IEnumerable and IEnumerator interfaces. The ICollection interface, in fact, inherits from the IEnumerable interface, thus "inheriting" its interface. The way these interfaces are implemented determine if the items will be stored in a particular order (sorted list, stack, or queue), if they are hashed for storage, and other behavior. The implementation also determines how items in storage get retrieved; for example, by index, by key, 'poped' in the case of a Stack, 'dequeued' in the case of a Queue, etc. Custom implementations of the interfaces mentioned above allow you to add some really slick functionality in your custom collection classes. In fact, the .NET Framework gives you a head start when designing your own collection classes by exposing two abstract classes, CollectionBase and DictionaryBase. These abstract classes already implement the fore-mentioned interfaces and provide the basic implementation, allowing you to further extend them for your own needs. Custom collection classes that inherit from these base classes or that are developed from scratch by totally custom-implementing all the necessary interfaces can expose their lists for iteration using standard For-Each statements (foreach in C#) as can all the standard collection types included with the .NET Framework (ArrayList, Hashtable, etc.). In VB .NET: For Each s_Name As String In o_MyCollectionOfNames ' Do whatever you want with s_Name Next
In C#: foreach(string s_Name in o_MyCollectionOfNames) { // Do whatever you want with s_Name }
The code above should be familiar to all of you, even those of you who have not made the transition from Visual Basic 6.0 yet. A tutorial that describes how to use these interfaces and abstract classes is perhaps an excellent topic for another article, but here I will concentrate on just two of these interfaces: IEnumerable and IEnumerator. The class I will iterate through is not a collection class because it does not inherit from either CollectionBase nor DictionaryBase, nor does it implement ICollection or IList. In fact, my class will not even contain a collection; it is just a couple of simple properties that define beginning and ending markers. Intrigued yet? Let's get going. Our 'Non-Collection' Class The class I will show you how to create represents a fiscal month and I'll call it FiscalMonth. You can find the complete code in Listing 1a and Listing1b. As many of you know from the companies your work for, a fiscal month does not always represent a calendar month, in fact it rarely does. The January fiscal month may very well start with December 27th of the previous year and end on January 26th, while the February fiscal month may begin on January 27th and end on March 1st. If you were to design a class as a standard collection class, you would expect it to contain a list with all the dates in the fiscal month. Instead, the FiscalMonth class will have only two primary properties: MonthBeg and MonthEnd; each declared as a DateTime type. Of course, this class can contain as much data and functionality as your application needs. Your goal is to be able to iterate through the dates in the fiscal month. In VB .NET: For Each o_Day As DateTime In o_FiscalMonth ' anything can go here Next
In C#: foreach(DateTime o_Day in o_FiscalMonth) { // anything can go here }
I'll explain the enumerating functionality in this class a little later. Right now I'll start with the enumerator that controls the iteration. | & | | 
By: Miguel Castro Miguel is an architect with IDesign who specializes in architecture consulting and building .NET solutions. He is a Microsoft MVP and INETA speaker and has been a software developer for over 22 years. With a Microsoft background that goes all the way back to VB 1.0 (and QuickBasic in fact), Miguel jumped on .NET as soon as the first public Beta was released and has provided .NET solutions for clients around the country in a variety of industries. He considers himself to be a .NET Developer and Architect and has equal love for both VB and C#, and no tolerance for language bigotry. He’s spoken at numerous user groups around the country as well as developer conferences.
He’s the author of the CodeBreeze code-generator, which among things can be found on his Web site:
www.steelbluesolutions.com
Miguel currently lives in Lincoln Park, NJ with his wife Elena and his daughter Victoria.
subscriptions@infotekcg.com | Fast Facts | | Develop custom enumerating functionality and take advantage of iteration through non-collection-based classes. | |
|