In Pascal’s triangle exercise in the exercism.io, the method signature is as below:
using System;
using System.Collections.Generic;
public static class PascalsTriangle
{
public static IEnumerable<IEnumerable<int>> Calculate(int rows)
{
…
}
}
It is obvious that the Calculate method is a method with nested generic type. I know that the IEnumerable<…> is the generic interface and it indicates the type of the method. And the IEnumerable is a generic interface and it works on the integer value type. But I cannot understand the meaning and purpose of the nested generic type, IEnumerable<IEnumerable>!
Here are my questions:
- What does it mean exactly?
- What should the returned type of the Calculate method be?
- Although the Calculate method is not inherited from the IEnumerable interface, should I implement the IEnumerable.GetEnumerator()?
1. What does it mean exactly?
In order to grasp this, it might help to have an understanding of what
IEnumerable<T>is, or what it represents. The definition from the docs is:In your case of
IEnumerable<IEnumerable<int>>, the definition could essentially be translated to:Which results in the nested iteration behavior that can be represented by a "collection of collections". Pascal's triangle is a good example of this because you have just that:
An example of this in code would be:
And then to get to the actual values inside, you need to iterate over each innerCollection within the outerCollection. For example:
Which gives output as:
2. What should the returned type of the Calculate method be?
In C#, you can represent this using anything that implements
IEnumerable<int>, for example a list of lists:Or an array of arrays:
Or a list of arrays:
Or an array of lists:
etc. etc.
3. Although the Calculate method is not inherited from the IEnumerable interface, should I implement the IEnumerable.GetEnumerator()?
You only need to implement
IEnumerable.GetEnumerator()in a custom type that implements theIEnumerableinterface. In your case, you can just return a type that already implements that interface (pretty much anything in System.Collections.Generic), as seen above. You'll obviously just need to build that instance dynamically given the amount ofrowspassed to the method, with a naïve example looking something like:Which when called, passing for example 3 as
rows, should result in: