C
C#12mo ago
jborean

Init only collection property contructor from IEnumerable

I was wondering if there was a way to assign an IEnumerable to a init only collection property. For example I can do
ProcessStartInfo psi = new()
{
ArgumentList = { "foo", "bar" },
};
ProcessStartInfo psi = new()
{
ArgumentList = { "foo", "bar" },
};
But I was wondering if I could somehow do
IEnumerable<string> arguments = ...;
ProcessStartInfo psi = new()
{
ArgumentList = arguments,
};
IEnumerable<string> arguments = ...;
ProcessStartInfo psi = new()
{
ArgumentList = arguments,
};
I'm currently just looping through the enumerable and doing psi.ArgumentList.Add(a); as a fallback but just wanted to check if there was another way
13 Replies
Keswiik
Keswiik12mo ago
Best you can do in this case would be IEnumerable<string> = new List<string>() { "foo", "bar" }
jborean
jboreanOP12mo ago
My use case is specifically where the enumerable is through an arg and wanting to set that as the ProcessStartInfo ArgumentList property. From what I can see online it doesn’t seem possible but I thought I would ask in case I’m missing something simple
TheBoxyBear
TheBoxyBear11mo ago
ProcessStartInfo.ArgumentList is a System.Collections.ObjectModel.Collection<string>, a class with an IList<T> constructor so you can simple convert the enumerable to a list and pass it
ProcessStartInfo psi = new()
{
ArgumentList = new(arguments.ToList()),
}
ProcessStartInfo psi = new()
{
ArgumentList = new(arguments.ToList()),
}
jborean
jboreanOP11mo ago
it's readonly so you can't set it or at least the only way I can set it is with = { "foo", "bar" },
TheBoxyBear
TheBoxyBear11mo ago
Learning something new :dviperHmm: Seems this syntax just calls Add under the hood anyway so looping and adding each item wouldn't be a huge deal in comparison So
ProcessStartInfo psi = new()
{
ArgumentList = { "foo", "bar" }
};
ProcessStartInfo psi = new()
{
ArgumentList = { "foo", "bar" }
};
would be equivalent to
ProcessStartInfo psi = new();
psi.ArgumentList.Add("foo");
psi.ArgumentList.Add("bar");
ProcessStartInfo psi = new();
psi.ArgumentList.Add("foo");
psi.ArgumentList.Add("bar");
but the collection initializer syntax is only possible during initialization
jborean
jboreanOP11mo ago
Makes sense, I'm just sticking with the foreach loop with Add 🙂
cap5lut
cap5lut11mo ago
since C# 12 u can use collection expressions
Collection expressions (Collection literals) - C#
Collection expressions are expressions that convert to many different collection types. They enable you to write literal values for collection elements, or import other collection elements into a new collection.
cap5lut
cap5lut11mo ago
eg IEnumerable<string> arguments = ["a", "bc", "def"]; or IEnumerable<string> arguments = [..someStringCollectionA, "b", ..someOtherStringCollectionC]; (.. is called spread operator here)
TheBoxyBear
TheBoxyBear11mo ago
The question is about initializing a get-only collection from an IEnumerable. The collection initializer is a workaround that allow adding items to a mutable collection when the reference itself is readonly
TheBoxyBear
TheBoxyBear11mo ago
Might want to keep an eye on future c# releases. It seems like a small oversight with all the syntax sugar that exists especially regarding collections in recent versions.
cap5lut
cap5lut11mo ago
i totally agree. optimizations for the collection literals will come (iirc some are already merged for .net 9), but generally speaking they provide a way that u would only have to recompile without touching the code at all to get new optimizations in, instead of using some self written code. (tho there are some uncommon use cases where u cant wait for better performance, but those ppl know what they are doing) sadly the whole thing doesnt apply here because collection literals require that u can assign a new instance

Did you find this page helpful?