Search code examples
c#listmultidimensional-arrayenumerable

How to I convert this manual code into using Enumerable.Range to initialize my multi-dimensional property?


This question is related to the code sample in the answer here (https://stackoverflow.com/a/70694640/2287576).

I now have this constructor:

public List<MSAHistoryItemStudent>[] StudentItems { get; set; }
public MSAHistoryWeek()
{
    TalkItems = Enumerable.Range(1, 6).Select(x => new MSAHistoryItemTalk()).ToList();
    Teaching = Enumerable.Range(1, 3).Select(x => string.Empty).ToList();
    StudentItemStudyNumbers = Enumerable.Range(1, 5).Select(x => string.Empty).ToList();
    StudentItemDescriptions = Enumerable.Range(1, 5).Select(x => string.Empty).ToList();

    StudentItems = new List<MSAHistoryItemStudent>[]
    {
        new List<MSAHistoryItemStudent>(),
        new List<MSAHistoryItemStudent>(),
        new List<MSAHistoryItemStudent>(),
    };

    foreach(var studentitems in StudentItems)
    {
        for(int i = 0; i < 5; i++)
        {
            studentitems.Add(new MSAHistoryItemStudent());
        }
    }
}

I can't work out the Enumerable.Range approach to pre-create StudentItems how I want:

  • I want an array of 3 List<MSAHistoryItemStudent>.
  • I want each of these arrays to have 5 MSAHistoryItemStudent elements.

Solution

  • As there is a relatively low number of lists, you can replace your calls to new with a call to Enumerable.Range:

    StudentItems = new 
    {
        Enumerable.Range(1, 5).Select(x => new MSAHistoryItemStudent()).ToList(),
        Enumerable.Range(1, 5).Select(x => new MSAHistoryItemStudent()).ToList(),
        Enumerable.Range(1, 5).Select(x => new MSAHistoryItemStudent()).ToList(),
    };
    

    Incidentally, if you put this somewhere:

    public static List<T> MakeN<T>(int n) where T:new()
      => Enumerable.Range(1,n).Select(x => new T()).ToList();
    

    Then you can simplify those calls some:

    TalkItems = MakeN<MSAHistoryItemTalk>(6);
    Teaching = new string[3].ToList();
    
    StudentItems = new
    {
        MakeN<MSAHistoryItemStudent>(5),
        MakeN<MSAHistoryItemStudent>(5),
        MakeN<MSAHistoryItemStudent>(5),
    };
    

    And everywhere else you're using Enumerable.Range.Select..

    ... apart from where you do it to string (for which I've given an alternative form).