Question regarding IEnumerable and IEnumerator

I use the following code so myClass can use foreach. But I'm pretty new to programming and have difficulty understanding the following code. I described my problems in the comments. I would appreciate some information.

public class MyClass : IEnumerable<string> { //1) What is IEnumerator for? // Whats the difference between IEnumerator and IEnumerable public IEnumerator<string> GetEnumerator() { yield return "first"; yield return "second"; } //2) What is it for? It just calls above method IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } //3) Lastly what benefits I have from implementing genetic interface //IEnumerable<string> instead of just IEnumerable 
+7
source share
6 answers

What is the difference between IEnumerator and IEnumerable?

Jason's answer is good, but I thought I would just add how I think about it. Imagine you have a sequence:

 1, 1, 2, 3, 5, 8, 13, ... 

Now imagine that you have an arrow pointing to some position in this sequence:

 1, 1, 2, 3, 5, 8, 13, ... ^ 

An arrow is an object that can do two things. First, he can give you what he points to. Secondly, he may indicate the following.

IEnumerator is an arrow. It has a Current property that gives you what it points to. It has a MoveNext () method that points to the following.

How do you get the arrow in the first place? You will need a factory arrow. You ask factory for the arrow, and it gives an arrow pointing to the first element in the sequence.

IEnumerable is a factory arrow. It has a GetEnumerator method that gives you an arrow to the first element of a sequence.

A good feature of this scheme is that you can have multiple arrows pointing to different places in the same sequence.

What are the benefits of implementing the universal IEnumerable interface, not just IEnumerable?

Suppose a sequence has integers. If you implement IEnumerable , then when you say

 foreach(int x in mysequence) 

what you really need to do is convert the int into a sequence into an object, an integer box, and then immediately return the object back to an integer, adding completely unnecessary memory allocation for each individual operation. If the compiler knows that the sequence has integers, then it may skip the unnecessary boxing operation.

Suppose a sequence has strings. If you implement IEnumerable<string> then you can say:

 string first = mysequence.First(); 

If you do not, you must say

 string first = (string)mysequence.First(); 

which is not necessary and error prone. Instead of instructing the compiler by casting that the type is a string, you can simply ensure that the type is a string using a type system.

+11
source

1) What is IEnumerator for? What is the difference between IEnumerator and IEnumerable ?

IEnumerator is an interface that introduces methods that allow you to list a sequence. The difference between IEnumerator and IEnumerable is that the former is a contract for objects that allow you to list a sequence, and the latter is a contract for objects that are a sequence that can be listed.

 public IEnumerator<string> GetEnumerator() { yield return "first"; yield return "second"; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } 

2) What is it for? It just calls the method above.

The first is an implementation of the GetEnumerator method on the IEnumerable<string> contract. The latter is an explicit implementation of the GetEnumerator method on the IEnumerable contract. The problem is that both contracts have a method called GetEnumerator , but with different return types, so the method cannot satisfy both contracts at the same time (any class that implements IEnumerable<T> must also implement IEnumerable as IEnumerable<T> : IEnumerable ) The latter calls the implementation of IEnumerable<string>.GetEnumerator , since it is a reasonable implementation that returns IEnumerator as IEnumerator<string> : IEnumerator .

3) And finally, what benefits do I get from implementing the universal IEnumerable<string> interface instead of just IEnumerable ?

Strong typing. You know that the elements in the IEnumerable<string> sequence are all String instances, while you do not know what IEnumerable for and may eventually try to pass the last element to the String instance when it cannot be.

+6
source

1) What is IEnumerator for?

IEnumerator is the real working part with the MoveNext () and Current elements.

What is the difference between IEnumerator and IEnumerable

IEnumerable is an interface to the collection that signals that it has GetEnumerator ().

2) [non-generic GetEnumerator] What for? It just calls the method above

An unconventional method exists only for backward compatibility. Note that it is moved “out of sight” as much as possible using an explicit implementation. Realize this because you must then forget about it.

3) Finally, what benefits do I get from implementing the IEnumerable genetic interface instead of IEnumerable

When used with foreach adavantage is small, since foreach will introduce a looping variable. This will allow you to use var in foreach:

 foreach (var s in myClassInstance) // needs `IEnumerable<string>` foreach (string s in myClassInstance) // works with `IEnumerable` as well 

But with IEnumerable<string> you also have a secure interface type for other areas, primarily LINQ:

 MyClass mc = new MyClass (); string s = mc.FirstOrDefault(); 
+3
source

This is the declaration for IEnumerable<T> :

 public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); } 

You have no choice, you also need to implement a non-generic IEnumerable interface. You will get a compilation error if you omit the implementation of IEnumerable.GetEnumerator (). This is the luggage left over from .NET 1.x days when generics were not yet available, and the transition period for .NET 2.0, where it needed to support interaction with .NET 1.x builds. We are stuck with it.

+3
source

GetEnumerator existed since, before generics were introduced into the language, so as not to violate existing code, the default method accesses the general implementation.

With a general enumeration, the consumer of your class does not need to throw each element into a string when repeating.

0
source

Regarding the third question (why use generics?), Here are a few answers:

Should we use the Generic Collection to increase safety and performance?

In short, use shared collections every time you can.

0
source

All Articles