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()?
Calculate is not a generic method. A generic method has angle brackets after the name with one or more "variables" in that are the unknown types you will refer to in the method, which mean they can look like:
What you're doing in the angle brackets is establishing a name alias for the types that will be used at runtime. When an actual type is used, anywhere you used that alias will behave as if you used the actual type:
Methods don't have a "type". They may return something that has a type and they may have parameters that are of a particular type, but in and of themselves methods have no type
Just appreciate that that it's one type inside another, and it can repeat for a long time:
It's a type. It's not a string, it's something that contains a collection of string and it can be enumerated. IEnumerable is the entire type of the thing. just like
string
appears inside the angle brackets andstring
is a type, so too isIEnumerable<string>
a type of thing. Because it's a type of thing it can appear inside the angle brackets of something else:VB.NET's syntax might be clearer:
Here are my questions:
It's an "x of y of z". If it were
IEnumerable<IList<IEnumerable<string>>>
it would be a "w of x of y of z". Other answers cover this in superb detail, so I won'tSomething that can be enumerated, that is full of subthings that can be enumerated. And those enumerable subthings have to be collections of
int
. In your "x of y of z", x and y are collections and z is an int.You don't inherit an interface, you implement it. Your class does not implement an IEnumerable because it doesn't seem to need to. If you wanted to provide a GetEnumerator method and be able to say
foreach var whatever in myPascalsTriangle
then you could implement IEnumerable.Your method is declared to return some other type that already implements IEnumerable, so you just have to comply with that by providing a type that implements it. You do not have to implement it on this class that contains the method (just like you don't have to implement string every time you want to use a string)
--
The main takeaways from this answer for you should really be in firming up the terminology - I think you might be slightly confused as to classes vs methods vs interfaces vs return types vs implementations. Classes represent things, they implement interfaces which then means they can be guaranteed to have methods with certain names and that return certain types. This then means that they can be treated in a common way.. But there isn't any need for a class to implement an interface just so that it can have a method that returns another type of class that already implements that interface