Search code examples
c#initializer

Can C# Collection Initializers accept a lambda generator or only fixed values


This is kind of a duplicate of c#, using lambdas with collection initialization, but its 13 odd years old and things have changed. Hopefully.

I'm writing a one off unit test, so I'm not looking for extension methods or something that requires lots of supporting code. I could probably have written the code in less time than this question takes, but now I'm curious and my Google-fu hasn't turned up anything useful/recent. A yes (and how)/no answer would suffice initially and reasons can follow later.

The MS docs on collection initializers indicate in one of their examples that you can use a method to return a single value. BUT, what about a collection instead? no mention. There is a (closed) 7 year old feature request for Roslyn which was never implemented, and now has dead links, that is similar to what I'm thinking.

How to do something like this without writing another function in the test class:

ClassA instanceA = new ClassA {
    MyListB = new List<ClassC>() { 
        () => { 
           List<ClassC> list = new List<ClassC>();
           for(int i = 0; i < 10; i++)
               list.add(new ClassC() {SomeProp = i});
           return list;
         }
    }
}

I suppose the extra nesting level is irrelevant for the question, it just matches my current structure.

I know I can write

List<ClassC> GetList() {
    List<ClassC> list = new List<ClassC>();
    for(int i = 0; i < 10; i++)
       list.add(new ClassC() {SomeProp = i});
    return list;
}

ClassA instanceA = new ClassA {
    MyListB = GetList()
}

Just curious as to if there is a different (more lazy?) way?

I'm using VS2022, the test project is xUnit using .Net Core 6, and the system under test is a .Net 4.6.1 dll project. Language version ranges through the various projects. It's irritating, but I'm working on it, I'm a new starter to an established solution.


Solution

  • Note that a collection initialiser is basically an array literal so using a method makes no sense. This should do what you want:

    ClassA instanceA = new ClassA
                       {
                           MyListB = Enumerable.Range(0, 10)
                                               .Select(i => new ClassC {SomeProp = i})
                                               .ToList()
                       };