Muhammet Topcu
Muhammet Topcu

Reputation: 51

Difference between using IEnumerator and using an array as an property

I get the idea of IEnumerator which gives an abilty of iteration to a class. I get the idea of why GetEnumerable() is needed to use foreach statement. But I wonder why I need to implement IEnumerator while I can declare an array as an property? I am really confused and could use a good explanation. Here is my codeblock, the result is the same with and without IEnumerator implementation.

static void Main(string[] args)
    {

        Customer customer1 = new Customer
        {
            Name = "Marty",
            Surname = "Bird",
            Id = 1
        };
        Customer customer2 = new Customer
        {
            Name = "Hellen",
            Surname = "Pierce",
            Id = 2
        };
        Customers customers = new Customers();
        customers.Add(customer1);
        customers.Add(customer2);
        //Using a property: This one works without an extra GetEnumerator implementation.
        foreach (var item in customers.CustomerList)
        {
            Console.WriteLine(item.Name);
        }
        //Using with GetEnumerator()
        foreach (Customer item in customers)
        {
            Console.WriteLine(item.Name);
        }

    }
    class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
    }

    class Customers:IEnumerable
    {
        private List<Customer> customerList = new List<Customer>();

        public List<Customer> CustomerList { get=> customerList; }
        public void Add(Customer p)
        {
            customerList.Add(p);
        }

        public IEnumerator GetEnumerator()
        {
            return customerList.GetEnumerator();
        }
    }

Upvotes: 3

Views: 206

Answers (4)

John Wu
John Wu

Reputation: 52260

If you want to roll your own enumerable Customers class, it is very easy:

class Customers : List<Customer>
{
}

That's it!

Now you can do this:

Customer customer1 = new Customer
{
    Name = "Marty",
    Surname = "Bird",
    Id = 1
};
Customer customer2 = new Customer
{
    Name = "Hellen",
    Surname = "Pierce",
    Id = 2
};
Customers customers = new Customers();
customers.Add(customer1);
customers.Add(customer2);
foreach (var item in customers)
{
    Console.WriteLine(item.Name);
}

That being said, you may want to read this answer: Is it a good practice to create your own collection class?. In most cases you can skip the special class and just use List<Customer> directly.

Upvotes: 2

ososnilknarf
ososnilknarf

Reputation: 76

You really don't need to implement IEnumerator at all. You can just get rid of the Customers class and replace the line:

Customers customers = new Customers();

with this:

List<Customer> customers = new List<Customers>();

The only reason you were required to implement GetEnumerator was because you had inherited the class Customers from IEnumerable, which is an interface that declares that method. All methods and properties in an interface must be implemented in a class that implements that interface.

Just given the code you've shown you don't need the Customers class, just use a List as I explained above.

However, if you really need a Customers class, because you plan to add more functionality to it than what you've shown, one option would be to inherit from List<Customer>. Then it would work in the foreach statement without needing to implement GetEnumerable() because List already implements that method.

Upvotes: 3

Abdul Moeez
Abdul Moeez

Reputation: 1401

Array properties often cause errors. We develop a reliable array property that avoids errors in foreach-loops. Microsoft suggests a design pattern that does not use the null value, even when there is no data.

class Program
{
    static void Main()
    {
        foreach (string item in Empty)
        {
            System.Console.WriteLine(item); // Never reached
        }
    }

    /// Get an empty array.
    public static string[] Empty
    {
        get
        {
            return new string[0]; // Won't crash in foreach
        }
    }
}

NET has its IEnumerable interface misnamed - it should be IIterable. Basically a System.Collection.IEnumerable or (since generics) System.Collection.Generic.IEnumerable allows you to use foreach on the object implementing these interfaces.IEnumerable, on the other hand, basically says that given a start position it is possible to get the next value. One example of this may be an infinite series of numbers:

public IEnumerable<int> Infinite()
{
    int i = 0;
    while(true)
        yield return i++;
}

Upvotes: 2

itsme86
itsme86

Reputation: 19496

It's because an array implements GetEnumerator(). Your class might not always store enumerable things in a data structure that already implements that for you though. You can get very creative as this pattern is extremely flexible.

Take this class as an example:

class Numbers1To5 : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator() => new Numbers1To5Enumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

    class Numbers1To5Enumerator : IEnumerator<int>
    {
        public int Current { get; private set; }
        object IEnumerator.Current => Current;

        public bool MoveNext()
        {
            if (Current >= 5)
                return false;

            Current++;

            return true;
        }

        public void Reset()
        {
            Current = 0;
        }

        public void Dispose()
        {
        }
    }
}

If you had a program that did the following, you'd get the numbers 1 through 5 displayed in the console:

foreach (int number in new Numbers1To5())
    Console.WriteLine(number);

Upvotes: 1

Related Questions