Why do we need IEnumerator and IEnumerable?
Asked Answered
P

5

4

Ok so I was just working through the IEnumerator and IEnumerable. Now the MSDN says that the main objective of these things is to iterate through a customer collection.

Fair enough I was however able to iterate through a custom collection without the use of either (or at least I'd like to think so)

namespace ienumerator
{

class person
{
    public person(string first, string second)
    {
        fname = first;
        lname = second;
    }
    public string fname { get; set; }
    public string lname { get; set; }
}

class person_list
{
    public person[] list;
    public person_list(person[] per)
    {
        list = new person[per.Length];
        for (int i = 0; i < per.Length; i++)
        {
            list[i] = per[i];
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        person[] names = new person[3]
        {
            new person("some","one"),
            new person("another","one"),
            new person("sss","ssdad"),
        };

        person_list list_of_names = new person_list(names);
        int i = 0;
        while (i < list_of_names.list.Length)
        {
            Console.WriteLine(list_of_names.list[i].fname);
            i++;
        }
        Console.Read();
    }
 }
}

So what is flawed in my understanding, the above is giving me the same result that I achieve after implementing IEnumerator and IEnumerable.

Pleistocene answered 16/12, 2012 at 14:36 Comment(5)
Check out "foreach": msdn.microsoft.com/en-us/library/vstudio/ttw7t8t6.aspxWoo
Now change type of list to LinkedListand try to compile it.Eccles
@2kay I am guessing there would be some type of length property issues ?Pleistocene
In your code int i is a simple (and exposed) iterator.Asphyxiate
Off topic but your variable names and naming conventions need to be improved. A param called "per" is not a good name because it doesn't mean anything. "person" however would be understood. Memory is cheap and plentiful these days. Saving 3 characters in a param name isn't doing you any good.Feeling
A
18

I was however able to iterate through a custom collection without the use of either

Of course you can iterate your own collection without the interface; if you couldn't, then how would you implement the interface?

You, as a code implementor, do not implement an interface for your convenience. You implement it for the convenience of the consumer of your code. The interface means "attention customer: you can enumerate the contents of this collection without having to know anything about how I implemented it".

That's the purpose of an interface: it provides an abstraction that allows consumers of your code to use it without having to understand how it works.

Alcides answered 16/12, 2012 at 16:49 Comment(11)
sry if it is a silly question but who is the consumer of my code ?Pleistocene
@WinCoder: Either you're writing these classes with the expectation that they will be used zero times in the future, or one or more times in the future. If you expect that the class will be used zero times in the future, then it doesn't matter what the class does because it will never be used. If you expect that it will be used one or more times in the future then the person using the class is the consumer. Note that the consumer might be yourself in the future. Make choices now that benefit your future self.Alcides
Having a hard time understanding ienumerable. I guess my IQ is too low for this stuff and will have to put in more hours. Anyways Thanks...Pleistocene
@WinCoder: Then ask a new question! That's what this site is for. But in short: IEnumerator is like a book. IEnumerable is like a reader. You can have many readers reading the same book, and each of them on a different page.Alcides
I learn best by example. I have been scouring the web for scenario where it is necessary to implement ienumerable and the code i wrote in the question wouldn't work in the example. If you find time could you please post such a scenario on codeproject or here on SO.Pleistocene
@WinCoder: The scenario is: someone who is not you wishes to use your type. Their task is to iterate over the members of the collection. You do them a kindness by enabling their using the standard IEnumerable/IEnumerator technique, so that they do not have to learn some new, different technique for iterating over your collection.Alcides
that would be one scenario. There are some other scenario's here #13903926Pleistocene
@EricLippert "IEnumerator is like a book. IEnumerable is like a reader." Is that what you intended to say? Sounds backwards to me.Rumania
@Mark: You are absolutely right, I said that backwards. Silly me!Alcides
@EricLippert, I am not sure I fully comprehend your book and reader analogy. Why do I need several readers if only one reader can read at a time? Similarly if a text reader is created each time GetEnumerator is called what's the benefit of creating multiple readers if due to I/O constraints only one reader can access a file at one time? I posted similar question here and do not understand the business of potentially n-readers that created quite some headache when I posted: #14040071Dodiedodo
Ancient question, but... @MattWolf - book and bookmarks may be better analogy - many people can grab the same book and leave bookmark (IEnumerator) at place where each stopped reading. It also demonstrates why modification of collection is an issues - someone can tear off pages with your bookmark and now it is lost...Haruspicy
H
2

In your main function you used two aspects of person_list to iterate through the list of people, Length and the [] operator for taking the member of a collection at a certain position.

However, what if you had some container or custom collection which didn't implement one or both of these? For example, a class that read a file line by line might not know in advance what the length of the collection was and so not define Length. An enumerator that reads messages from a queue might only be able to take the next one, and not one, say, four positions ahead with [4]. In both cases you can still 'iterate' through the collection properly.

IEnumerator and IEnumerable require exactly the attributes that are needed for foreach to work and no others, which is why functions can use them as requirements, knowing that they will be able to iterate through whatever type of collection they get passed.

Hanzelin answered 16/12, 2012 at 14:47 Comment(1)
Now these are some compelling arguments.Pleistocene
D
1

You can of course iterate over a custom collection without implementing the IEnumerable interface, but then the iterating code has to know your custom collection.

If you implement IEnumerable, the code that iterates over all elements does not need to know your person_list class. It uses an instance of some class that implements IEnumerable, and it will still work if you exchange the actual instance for something else that also implements IEnumerable later on.

Dolan answered 16/12, 2012 at 14:42 Comment(1)
Ok so it means i don't have to write while loop for every different kind of collection right ?Pleistocene
S
1

Actually, in C#, it is not required to implement the IEnumerable and IEnumerator to customize you own collections. If you iterate the collection by using traditional way that is fine for you, but it will be trouble if you use foreach to iterate the collection.

Another reason, if you want to expose your class so that VB.NET user can employ you should consider to implement the both interface.

Be note that IEnumerable is difference in non-generic and generic collection. The non-generic one belong to System.Collection the other is belong to System.Collection.Generic namespace

Sternmost answered 1/11, 2014 at 6:53 Comment(0)
C
0

There is a plenty of ways to iterate over custom sequence. One way to do this is to use Iterator Design Pattern.

Iterator Pattern is used to unify traversing over custom sequence (it could be a collection in memory, generated collection or something else). In .NET world this pattern implemented in the following way: we have a iterable object that implements IEnumerable interface (and this shows to any customer of your class that you have a ability for traversing your content).

And we have a iterator itself (object that implements IEnumerator interface) that you can treat as a "pointer" to current position in your iterable object. Because you may have inner loops (i.e. multiple iterations over the same object in one time) you have to split iterable object from the iterator.

Basically there is a plenty of ways to traverse a specific sequence, but Iterator Pattern gives you an ability to "generalize" this approach hiding particular implementation of the traversing algorithm from the callers inside the implementation.

Celloidin answered 19/12, 2012 at 20:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.