Is feasible to use the spread operator to init a collection with another collection?

123 views Asked by At

Nothing important, just for sake of curiosity.

Given the following snippet, we know we can initialize the MyList list during the C instance construction thanks to a special syntactic sugar:

public class C {
    private List<int> _myList = new();
    public IList<int> MyList => this._myList;
}

public class D {
    public void Prova() {
        var c1 = new C() {
          MyList = { 1, 2, 3 }  //here
        };
    }
}

However, if we need to pull the number of from another list/array, I wonder if there is a similar "concise" way instead of adding each number after the instance creation.

That is:

public class D {
    public void Prova() {
        var c1 = new C() {
          MyList = { 1, 2, 3 }
        };
        
        IList<int> list2 = [4, 5, 6];
        
        //classic approach, more verbose
        var c2 = new C();
        foreach (int n in list2) {
            c2.MyList.Add(n);
        }
        
        //just a suggestion (does not compile)
        var c3 = new C() {
          MyList = { ..list2 }  //clues?
        };
    }
}

Any clue? worthwhile?

UPDATE: my fault. I didn't specify that the C class (hence the MyList signature) cannot be changed.

I know there are plenty of solutions as workaround, but my question is strictly toward a possible syntactic sugar to achieve the goal.

UPDATE 2: I just noticed that the spread operator for arrays works basically the same as it were to fill the list up:

    IList<int> list2 = [4, 5, 6];
    
    IList<int> a = [..c1.MyList, ..list2];

Behind the scenes, the actual code is rather complex. However, it's clear that a new array is created by iterating the two sources.

At this point, it would be simple to call the Add method, as the compiler does in the first snippet.

1

There are 1 answers

0
jakub podhaisky On

To my Knowledge the concise syntax you're hoping for with MyList = { ..list2 } does not exist in C# The collection initializer syntax only supports adding individual elements

However, you can achieve a more concise way of adding all elements from another collection to MyList without manually iterating over them with a foreach loop

Just modify C class to include a method that will add entire range

public class C
{
    private List<int> _myList = new();

    public IList<int> MyList => _myList;

    // Add this method to allow adding a range of elements
    public void AddRange(IEnumerable<int> range)
    {
        _myList.AddRange(range);
    }
}

than we can use the range in D

public class D
{
    public void Prova()
    {
        var c1 = new C()
        {
            // Initialize with individual elements
            MyList = { 1, 2, 3 }
        };

        IList<int> list2 = new List<int> { 4, 5, 6 };
        
        // Use AddRange to add elements from another collection
        var c2 = new C();
        c2.AddRange(list2);
    }
}