It’s 2021, and you’re still confused about the `IEnumerator` and `IEnumerable` interfaces?

It’s 2021, and you’re still confused about the `IEnumerator` and `IEnumerable` interfaces?

[[375509]]

This article is reprinted from the WeChat public account "Full Stack Coder Portrait", the author is Xiaomajia. Please contact the Full Stack Coder Portrait public account for reprinting this article.

The two interface words IEnumerator and IEnumerable are similar and have related meanings, and it is difficult to distinguish them.

After many years in the industry, I have never systematically sorted out this pair of Li Kui and Li Gui.

Recently, I have been arguing with the article "Actually, LRU is just so-so" by the God of Why. Solution 1 uses an array to implement LRU. The handwritten algorithm involves this pair of interfaces. I will take this opportunity to cover this pair of difficult enemies.

IEnumerator

The IEnumerator and IEnumerable interfaces have similar names and are often used together, but they have different purposes.

The IEnumerator interface provides a way to iterate over a collection within a class. IEnumerator requires you to implement three methods:

  1. MoveNext method: This method increases the collection index by 1 and returns a bool value indicating whether the end of the collection has been reached.
  2. Reset Method: It resets the collection index to its initial value -1, which invalidates the enumerator.
  3. Current method: Returns the current object at position

IEnumerable

The IEnumerable interface provides support for foreach iteration. IEnumerable requires you to implement the GetEnumerator method.

  1. public IEnumerator GetEnumerator()
  2. {
  3. return (IEnumerator)this;
  4. }

Which interface should I use?

Based on the above words alone, it is difficult to distinguish the usage scenarios of the two interfaces.

The IEnumerator interface defines how to iterate over collection-type objects in a class.

The IEnumerable interface allows enumeration using a foreach loop.

Therefore, the GetEnumerator method of the IEnumerable interface returns an IEnumerator interface. To implement IEnumerable, you must also implement IEnumerator.

From the English root:

The IEnumerator interface represents an enumerator, which defines the enumeration method and is a noun.

The IEnumerable interface represents that the object has the property of being enumerable and is an adjective.

In short, if you want to provide support for foreach, then make the object enumerable first, and then talk about the enumeration method, that is, implement these two interfaces.

Best Practices

  • Implement IEnumerator in a nested class so you can create multiple enumerators.
  • Provides exception handling for the IEnumerator's Current method.

Why do this?

If the contents of the collection change, the reset method will be called, and then the current enumerator will be invalid, and you will receive an IndexOutOfRangeException (other situations may also cause this exception). So a Try...Catch block is executed to catch this exception and throw an InvalidOperationException, indicating that modifying the collection content is not allowed while iterating.

"This is also the reason why we often get an InvalidOperationException when trying to modify the iterated object in foreach.

The following uses the car list as an example to implement the IEnumerator IEnumerable interface

  1. using System;
  2. using System.Collections;
  3. namespace ConsoleEnum
  4. {
  5. public class cars : IEnumerable
  6. {
  7. private car[] carlist;
  8.    
  9. // Create internal array in constructor.
  10. public cars()
  11. {
  12. carlist= new car[6]
  13. {
  14. new car( "Ford" ,1992),
  15. new car( "Fiat" ,1988),
  16. new car( "Buick" ,1932),
  17. new car( "Ford" ,1932),
  18. new car( "Dodge" ,1999),
  19. new car( "Honda" ,1977)
  20. };
  21. }
  22. //private enumerator class
  23. private class MyEnumerator:IEnumerator
  24. {
  25. public car[] carlist;
  26. int position = -1;
  27.  
  28. //constructor
  29. public MyEnumerator(car[] list)
  30. {
  31. carlist=list;
  32. }
  33. private IEnumerator getEnumerator()
  34. {
  35. return (IEnumerator)this;
  36. }
  37. //IEnumerator
  38. public bool MoveNext()
  39. {
  40. position++;
  41. return (position < carlist.Length);
  42. }
  43. //IEnumerator
  44. public void Reset()
  45. {
  46. position = -1;
  47. }
  48. //IEnumerator
  49. public object Current  
  50. {
  51. get
  52. {
  53. try
  54. {
  55. return carlist[position];
  56. }
  57. catch (IndexOutOfRangeException)
  58. {
  59. throw new InvalidOperationException();
  60. }
  61. }
  62. }
  63. } // end nested class
  64. public IEnumerator GetEnumerator()
  65. {
  66. return new MyEnumerator(carlist);
  67. }
  68. }
  69. }

When foreach cars, you can clearly see

  • The foreach syntax sugar first encounters the enumerable cars. It actually accesses the GetEnumerator() method implemented by cars to get the iterator
  • Foreach each iteration actually accesses the Current property of the iterator

<<:  The current dilemma facing 5G: alarming power consumption and slower-than-expected base station construction speed

>>:  Review of 5G industry-specific networks in 2020: The beginning of a new era

Recommend

Charter to spend $442 million to boost broadband coverage

Charter Communications Inc, which provides intern...

A Deep Dive into Data Link Layer Devices

In computer networks, there are multiple layers t...

Global IT spending to reach $4.1 trillion in 2021, exceeding estimates

[[391876]] Recently, market research firm Gartner...

3 outages within 1 month, is the 5G core public cloud reliable?

[[442675]] This article is reprinted from the WeC...

The role of fiber in integrated infrastructure development

In the past, people settled near the banks of riv...

Internetport: €2/month KVM-512MB/10G SSD/5TB/Sweden VPS

Here is another VPS host in an unpopular area. In...