How to Use Custom Collections in your C# Application with IEnumerable and IEnumerator

How to Use Custom Collections in your C# Application with IEnumerable and IEnumerator


Sometimes, the available collections of C# will not be good enough for a project. From the implementation of IEnumerable and IEnumerator you can develop your custom collections supporting iteration via foreach :.

In this blog post, you will learn how to create your custom collection step by step and implement the IEnumerable and IEnumerator interfaces.

Why Use IEnumerable and IEnumerator?


IEnumerable allows iteration of a collection with a foreach statement.

IEnumerator is the abstraction providing the ability to iterate through the collection's elements.

Implementing these interfaces gives your custom collection an experience as smooth as one of the built-in collections.

Implementation of a Step-by-Step Procedure

Let's implement a simple custom collection named MyCollection that contains integers and supports iteration.




1. The Class Definition of MyCollection


Let's define a class that implements IEnumerable<int>.




using System;

using System.Collections;

using System.Collections.Generic;




public class MyCollection : IEnumerable<int>

{

private List<int> _items = new List<int>();




// Add method to add items to the collection

public void Add(int item)

{

_items.Add(item);

}




// Implement the GetEnumerator method

public IEnumerator<int> GetEnumerator()

return new MyEnumerator(_items);

}




// Explicit implementation of IEnumerable.GetEnumerator

IEnumerator IEnumerable.GetEnumerator()

{

return GetEnumerator();

}

}




2. Define the MyEnumerator Class


Now, we'll let the IEnumerator<int> interface in one class handle the traversal separately,




public class MyEnumerator: IEnumerator<int>

{

private readonly List<int>_items;

private int_position = - 1; // Before first element



public MyEnumerator(List<int> items )

{

_items = items;

}




// Current property to return the current element

public int Current => _items[_position];




object IEnumerator.Current

{ get { return Current; } }




// MoveNext method to advance to the next element

public bool MoveNext()

{

_position++;

return _position < _items.Count;

}




// Reset method to reset the position

public void Reset()

_position = -1;

}




// Dispose method (no unmanaged resources, so nothing to dispose)

public void Dispose()

{

}

}




Using the Custom Collection


Let's use our MyCollection class and MyEnumerator class in a simple program now that we have them set up.

class Program

static void Main()

{

MyCollection collection = new MyCollection();




collection.Add(1);

collection.Add(2);

collection.Add(3);

collection.Add(4);




foreach (int item in collection)

{

Console.WriteLine(item);

}

}

}




Output:




1

2

3

4

Breakdown of the Code


1. MyCollection Class


Implements IEnumerable<int>, allowing it to be used in foreach loops.

The Add method lets you add integers to the collection.

The GetEnumerator method returns an instance of MyEnumerator for iteration.

2. MyEnumerator Class


Implements IEnumerator<int>, which manages the iteration state.

MoveNext advances the iterator and returns false when the end is reached.

Reset resets the iterator to the start.

Current returns the current item during iteration.

Best Practices and Tips


1. Dispose Method: If your enumerator uses unmanaged resources, ensure Dispose properly cleans them up.

2. Yield Return: For simpler collections, consider using yield return in the GetEnumerator method instead of creating a separate enumerator class.

3. Thread-Safety: Be careful if your collection is accessed by multiple threads.

Using yield return (Alternative Implementation)

Here is an easy version of MyCollection with yield return:




public class MyCollection : IEnumerable<int>

{

private List<int> _items = new List<int>();




public void Add(int item)

_items.Add(item);

}




public IEnumerator<int> GetEnumerator()

foreach (var item in _items)

{

yield return item;

}

}




IEnumerator IEnumerable.GetEnumerator()

{

return GetEnumerator();

}

}




This approach avoids creating a separate IEnumerator class, making the code cleaner for simpler cases.




Conclusion


By implementing IEnumerable and IEnumerator, you can create robust, customizable collections in C#. Whether you need full control over the iteration process or a simplified version with yield return, these interfaces provide flexibility and power.

Happy coding!

Tags

Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.