Current .Net Version: 2.0.50727
Home
Articles
C# & .Net Framework Reference
Practice C# Online
XML Web Services
RSS Feeds
Code Snippets
T-SQL Scripts
Videos
Valuable Links
Contact Us
Mike's C#, VS.NET and SQL Blog




ROR XML Info.
Exploring Non-Generic Collections
Author: Michael G.     Last Updated:4/7/2006 12:00:06 PM
Category(ies): .Net Framework 1.0, .Net Framework 1.1, .Net Framework 2.0
Description: Learn all about the various types of non-generic collections in .Net.
  Add & View Comments About this Article

Tested with Microsoft Visual Studio 2005 8.0.50727.42; .NET Framework 2.0.50727

  • Exploring the Non-Generic Collection Interfaces
  • .Net Collection Interfaces

  • IEnumerable: This is a base System.Collection namespace interface. It enables foreach iterations over an underlying collection of objects. To be able to use foreach against a collection in a class or struct, that class or struct must implement the IEnumerable interface. The IEnumerable interface requires that you implement just one method: GetEnumerator(). GetEnumerator() returns an object that implements the IEnumerator interface (discussed below). public partial class MyClass { public MyClass() { TestCollection test = new TestCollection(); // We can use foreach because TestCollection implements IEnumerable. // Actually, any class that contains a GetEnumerator() method that // returns an IEnumerator object can be used. foreach (Object obj in test) { } } } public class TestCollection : IEnumerable { // I'm using another collection, but we can use our own. ArrayList al = new ArrayList(); public IEnumerator GetEnumerator() { return this.al.GetEnumerator(); } } Note that if you want to use a for iteration, you have to implement the IEnumerator interface directly.
  • IEnumerator: This is a base System.Collection namespace interface. All non-generic enumerators are derived from the IEnumerator interface. It is IEnumerator that really allows a foreach iteration, and it's the type returned by GetEnumerator() method in the IEnumerable interface. If you're dealing with other collections, such as an Arraylist in the preceding example, you won't need to implement your own enumerators. However, if you want to either 1) improve performance and/or 2) specifically control how your collection is enumerated through, then you'll want to implement your own enumerator via the IEnumerator interface.

    The IEnumerator interface implements the MoveNext() and Reset() mehtods and the Current property. The MoveNext() method should return true IF moving to the next ordinal in the collection/list of objects is possible; otherwise, it should return false. The Reset() method should reset the ordinal/index to a baseline value (in this case -1). The Current property returns the object in the collection/list at the current oridinal/index.

    Below is an example of a class that implements both the IEnumerator and IEnumerable interfaces. The underlying collection is an array of Strings (System namespace). This class does two things: 1) It returns an IEnumerator object that makes a foreach iteration possible, and 2) it implements this IEnumerator itself.

    public MyMethod() { MyABCs myABCs = new MyABCs(); foreach (Object o in myABCs) { // This would not be possible IF MyABCs did NOT // implement the IEnumerable interface! // Note: You do NOT need to implement IEnumerable // in order to make a foreach iteration possible. // All you need is to have a GetEnumerator() method // present. } } public class MyABCs : IEnumerator, IEnumerable { // This field stores the current index/ordinal: private int intCurrentIndex = -1; // This array stores the underlying collection: private String[] arrStrings; // This is the constructor for this class: public MyABCs() { this.arrStrings = new String[3]; this.arrStrings[0] = "A"; this.arrStrings[1] = "B"; this.arrStrings[2] = "C"; } // This property implements the IEnumerator interface: public object Current { get { if (this.intCurrentIndex > -1 && this.intCurrentIndex <= (this.arrStrings.Length - 1)) return this.arrStrings[this.intCurrentIndex]; else return null; } } // This method implements the IEnumerator interface: public bool MoveNext() { if ((this.intCurrentIndex + 1) <= (this.arrStrings.Length - 1)) { this.intCurrentIndex++; return true; } else return false; } // This method implements the IEnumerator interface: public void Reset() { this.intCurrentIndex = -1; } // This method implements the IEnumerable interface: public IEnumerator GetEnumerator() { return this; } } The preceding class does not need to implement its own IEnumerator members because the underlying collection, String[], already contains a GetEnumerator() method that makes a foreach iteration possible. Therefore, we could rewrite the preceding class as follows: public class MyABCs : IEnumerable { // This array stores the underlying collection: private String[] arrStrings; // This is the constructor for this class: public MyABCs() { this.arrStrings = new String[3]; this.arrStrings[0] = "A"; this.arrStrings[1] = "B"; this.arrStrings[2] = "C"; } // This method implements the IEnumerable interface: public IEnumerator GetEnumerator() { return this.arrStrings.GetEnumerator(); } } As a matter of fact, the two preceding examples above do not even need to implement any of the two interfaces. So long as they contain all of the necessary methods and properties that makes foreach iteration possible, they can work just fine without them having to implement any interfaces. public class MyABCs { // This array stores the underlying collection: private String[] arrStrings; // This is the constructor for this class: public MyABCs() { this.arrStrings = new String[3]; this.arrStrings[0] = "A"; this.arrStrings[1] = "B"; this.arrStrings[2] = "C"; } // This method implements the IEnumerable interface: public IEnumerator GetEnumerator() { return this.arrStrings.GetEnumerator(); } } The problem with not implementing interfaces in this way is that COM compliant components will not be able to iterate through the collection in such classes and structs. Not only that, but you won't even be able to cast the class or struct to a generic IEnumerator or IEnumerable object. public MyMethod() { MyABCs myABCs = new MyABCs(); IEnumerable oEnum = myABCs; // Oops! Error! MyABCs doesn't implement IEnumerable! // "Cannot implicitly convert type 'MyABCs' to 'System.Collections.IEnumerable'" foreach (Object o in oEnum) { } } public class MyABCs { // This array stores the underlying collection: private String[] arrStrings; // This is the constructor for this class: public MyABCs() { this.arrStrings = new String[3]; this.arrStrings[0] = "A"; this.arrStrings[1] = "B"; this.arrStrings[2] = "C"; } // This method implements the IEnumerable interface: public IEnumerator GetEnumerator() { return this.arrStrings.GetEnumerator(); } } So, it's best to always implement an interface so that interoperability and compatibility can and will be maintained. If you don't, Visual Basic and other COM-compliant technologies will not be able to iterate through the collections.


  • Comments Click Here to Add your Comment
    By eshwar @ 11/5/2007 5:49:46 AM

    its fine
    By bntycmgz @ 12/30/2007 9:36:18 PM

    >a href="http://rtegjgoz.com"<qjzihvhw>/a<  fwbltogy http://duxsozez.com rboifmpf gdlwdwnm  [URL=http://xqssssnb.com]umdrleem[/URL]
    By zpasadiz @ 2/23/2008 12:23:42 PM

    ughqkfea http://htsdiwmy.com ustwqeza hbciyfvi  [URL=http://lktcvwku.com]tltdmspa[/URL] ; >a href="http://wswwtsji.com"<bdwavzvt>/a<
     
    COPYRIGHT/DISCLAIMER | CONTACT US