Reputation: 690
I have a class with a get-only collection property. I would like to initialize the collection with the values from an existing collection.
I know that it is possible to initialize the collection using a collection initializer. I could also create the object and then use AddRange
on the collection to add the items of the existing collection. This would however create the object with an empty list and add the existing items afterwards.
Is there a way to create the object with the List properly initialized in the first place (without adding a constructor, of course)?
using System.Collections.Generic;
namespace EmptyConsoleApp
{
internal class Program
{
public static void Main(string[] args)
{
// Compiles, but is not what I need
var firstHolder = new Holder()
{
TheList = {"A", "B"}
};
// Compiles, but initializes the list after object creation
var existingList = new List<string>() {"Foo", "Bar"};
var secondHolder = new Holder();
secondHolder.TheList.AddRange(existingList);
// Does not compile
var thirdHolder = new Holder()
{
TheList = {existingList}
};
}
}
internal class Holder
{
public Holder()
{
TheList = new List<string>();
}
public List<string> TheList { get; }
}
}
Upvotes: 6
Views: 1608
Reputation: 97
it is not possible to initialize a read only property from outside of the class itself.
collection initializer is just a simplified syntax version and it does not mean using this syntax you have the same access as if you are in the class constructor
thirdHolder.TheList = existingList; // this is the traditional way
Perhaps you can use factory class pattern like this
internal class Program
{
public static void Main(string[] args)
{
// Compiles, but is not what I need
var firstHolder = new Holder()
{
TheList = { "A", "B" }
};
// Compiles, but initializes the list after object creation
var existingList = new List<string>() { "Foo", "Bar" };
var secondHolder = new Holder();
secondHolder.TheList.AddRange(existingList);
// Does not compile
//var thirdHolder = new Holder()
//{
// TheList = existingList
//};
//thirdHolder.TheList = existingList; // this is the traditional way
var thirdHolder = Holder.HolderFactory(existingList);
}
}
internal class Holder
{
public Holder()
{
TheList = new List<string>();
}
public static Holder HolderFactory(List<string> theList)
{
return new Holder(theList);
}
private Holder(List<string> theList)
{
this.TheList = theList;
}
public List<string> TheList { get; }
}
Upvotes: 0
Reputation: 77304
Is there a way to create the object with the List properly initialized in the first place (without adding a constructor, of course)?
It's not. That's what a constructor does. If you don't want to do it in the constructor, there is no way to do it.
Upvotes: 0
Reputation: 156988
No. You can't assign this read-only property from a collection initializer. It is read-only after all.
TheList = { "A", "B" }
works since it calls Add
on TheList
(once for each item added), it doesn't create and assign a new instance, which it is not allowed to.
TheList = { existingList }
doesn't work since there is a typing issue (TheList = { existingList[0] }
does work).
The best option you have it to create a constructor parameter and drop your idea of using collection initializers for something it isn't fit for.
Upvotes: 3