Differencebetween Ienumerator and Ienumerable

What is the difference between IEnumerator and IEnumerable?

IEnumerable is an interface that defines one method GetEnumerator which returns an IEnumerator interface, this in turn allows readonly access to a collection. A collection that implements IEnumerable can be used with a foreach statement.

Definition

IEnumerable 

public IEnumerator GetEnumerator();

IEnumerator

public object Current;
public void Reset();
public bool MoveNext();

example code from codebetter.com

when implementing iterator, what's the difference between returning IEnumerator or IEnumerable?

IEnumerable and IEnumerator are two different things.

IEnumerable<T> is a sequence that can be iterated over.

IEnumerator<T> is an object that is returned by IEnumerable<T> to iterate once over the sequence.

In general, the only place to return IEnumerator<T> is in the GetEnumerator() method.

yield return behaves the same way for both types, except that an iterator method that returns IEnumerable<T> can execute multiple times (each time the sequence is enumerated).

For more information on how this works, see Jon Skeet's article.

Can anyone explain IEnumerable and IEnumerator to me?

for example, when to use it over foreach?

You don't use IEnumerable "over" foreach. Implementing IEnumerable makes using foreach possible.

When you write code like:

foreach (Foo bar in baz)
{
...
}

it's functionally equivalent to writing:

IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
bar = (Foo)bat.Current
...
}

By "functionally equivalent," I mean that's actually what the compiler turns the code into. You can't use foreach on baz in this example unless baz implements IEnumerable.

IEnumerable means that baz implements the method

IEnumerator GetEnumerator()

The IEnumerator object that this method returns must implement the methods

bool MoveNext()

and

Object Current()

The first method advances to the next object in the IEnumerable object that created the enumerator, returning false if it's done, and the second returns the current object.

Anything in .Net that you can iterate over implements IEnumerable. If you're building your own class, and it doesn't already inherit from a class that implements IEnumerable, you can make your class usable in foreach statements by implementing IEnumerable (and by creating an enumerator class that its new GetEnumerator method will return).

Why do we need IEnumerator and IEnumerable?

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.

Why does interface IEnumerable return IEnumerator GetEnumemrator()? Why not just implement interface IEnumerator?

You can check the differences at this very nice article

TL;DR - Effectively, the IEnumerable contract assumes that you have a way of maintaning the state of the Enumerable.

Similarities

Both of these interfaces help to loop through the collection.

Relation

The IEnumerable interface actually uses IEnumerator. The main reason to create an IEnumerable is to make the syntax shorter and simpler.

If you go to the definition of the IEnumerable interface, you will see this interface has a method GetEnumerator() that returns an IEnumerator object back.

Differences

The main difference between IEnumerable and IEnumerator is an IEnumerator retains its cursor's current state.

When to use:

So, if you want to loop sequentially through the collection, use an IEnumerable interface else if you want to retain the cursor position and want to pass it from one function to another function then use an IEnumerator interface.

Example:

static void iEnumeratorMethodOne(IEnumerator<string> i)  
{
while(i.MoveNext())
{
Console.WriteLine(i.Current);

if(i.Current == "June")
{
iEnumeratorMethodTwo(i);
}
}
}

static void iEnumeratorMethodTwo(IEnumerator<string> i)
{
while(i.MoveNext())
{
Console.WriteLine(i.Current);
}
}

Difference between IEnumerable and IEnumerableT?

Basically the nongeneric interfaces came first, in .NET 1.0 and 1.1. Then when .NET 2.0 came out, the generic equivalents came out. Life would have been a lot simpler if generics had made it into .NET 1.0 :)

In terms of implementing "only" IEnumerable<T> instead of both - you basically have to implement both, and you have to use explicit interface implementation too, given that both define a parameterless GetEnumerator method. As IEnumerator<T> extends IEnumerator too, it's normally something like this:

public IEnumerator<T> GetEnumerator()
{
// Return real iterator
}

// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
// Delegate to the generic implementation
return GetEnumerator();
}

On the other hand, with the iterator blocks introduced in C# 2 (with yield return etc) you rarely need to implement these things entirely by hand, fortunately. You may need to write something like the above, and then use yield return in the GetEnumerator method.

Note that IList<T> does not extend IList, and ICollection<T> does not extend ICollection. That's because it's less type-safe to do so... whereas any generic iterator can be seen as a nongeneric iterator due to the (potentially boxing) conversion of any value to object, IList and ICollection allow values to be added to the collection; and it doesn't make sense to add (say) a string to an IList<int>.

EDIT: The reason why we need IEnumerable<T> is so that we can iterate in a type-safe way, and propagate that information around. If I return an IEnumerable<string> to you, you know that you can safely assume everything returned from it will be a string reference or null. With IEnumerable, we had to effectively cast (often implicitly in a foreach statement) each element that was returned from the sequence, because the Current property of IEnumerator is just of type object. As for why we still need IEnumerable - because old interfaces never go away, basically. There's too much existing code using it.

It would have been possible for IEnumerable<T> not to extend IEnumerable, but then any code wanting to make use of an IEnumerable<T> couldn't call into a method accepting IEnumerable - and there were a lot of methods like that from .NET 1.1 and 1.0.

IEnumerableT provides two GetEnumerator methods - what is the difference between them?

If you are implementing the IEnumerable<T> generic interface, you will pretty much always have to use the generic GetEnumerator method - unless you cast your object explicitly to (non-generic) IEnumerable.

The reason is backwards compatability with .NET 1.0/1.1 which didn't support generics.

Difference between using IEnumerator and using an array as an property

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.

C# Class is IEnumerable AND an IEnumerator at the same time. What are the issues with this?

Reduce your confusion (?) by using the generic versions of IEnumerable and IEnumerator.

A permutation enumerable is IEnumerable<IEnumerable<T>>. So you might have something like

IEnumerable<IEnumerable<T>> GetPermutations(IEnumerable<T> sequence)
{
return new Permuter<T>(sequence);
}

and

public class Permuter<T> : IEnumerable<IEnumerable<T>> { ... }

Furthermore, I've seen more than one case where a single type implemented both IEnumerable<T> and IEnumerator<T>; its GetEnumerator method was simply return this;.

I think such a type would need to be a struct, though, because if it were a class you'd have all sorts of problems if you called GetEnumerator() a second time before the first enumeration was completed.

EDIT: Consuming the permuter

var permuter = GetPermutations(sequence);
foreach (var permutation in permuter)
{
foreach (var item in permutation)
Console.Write(item + "; ");
Console.WriteLine();
}

Assuming the input sequence is { 1, 2, 3 }, the output is

1; 2; 3; 
1; 3; 2;
2; 1; 3;
2; 3; 1;
3; 1; 2;
3; 2; 1;

EDIT:

Here's a super-inefficient implementation to illustrate the suggestion:

public class Permuter<T> : IEnumerable<IEnumerable<T>>
{
private readonly IEnumerable<T> _sequence;

public Permuter(IEnumerable<T> sequence)
{
_sequence = sequence;
}

public IEnumerator<IEnumerable<T>> GetEnumerator()
{
foreach(var item in _sequence)
{
var remaining = _sequence.Except(Enumerable.Repeat(item, 1));
foreach (var permutation in new Permuter<T>(remaining))
yield return Enumerable.Repeat(item, 1).Concat(permutation);
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}


Related Topics



Leave a reply



Submit