0

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.
Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164

2 Answers2

2

Just nest another one of those Enumerable.Range(...)... calls in the Select call.

StudentItems =
    Enumerable.Range(1, 3).Select(x =>
        Enumerable.Range(1, 5).Select(y =>
            new MSAHistoryItemStudent()
        ).ToList()
    ).ToArray();
Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

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).

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • Thanks. I have added adopted this approach. I added that `MakeN` as a member of the `MSAHistoryWeek` class. – Andrew Truckle Jan 13 '22 at 20:31
  • Actually, I have reverted to the long hand `Enumerable.Range` approach. When I did it using `MakeN` I was getting null exceptions where I used `XText`. And that call is only used with the `StudentItems` object.. Reverting to your original suggestion works. – Andrew Truckle Jan 13 '22 at 20:37
  • Perhaps `StudentItems = new []` should have been `new List[]`? – Andrew Truckle Jan 13 '22 at 20:39
  • 1
    My bad, that was indeed a typo to put the `[]` in; I've taken it out as modern c# only needs the type on one side of the `=` and it's not fussy which eg `var x = new List[] {...}` or `List[] x = new {...}` (your property already defines the type in this latter form). Older c# needs it on both. You'll get a syntax error if your c# is too old to understand it) – Caius Jard Jan 13 '22 at 20:48