Collection initialisers on immutable collections don't work #3210
Replies: 11 comments
-
This variant would be a breaking change for Also, there has been previous discussion related to this issue on #463. |
Beta Was this translation helpful? Give feedback.
-
@svick Thanks, I searched beforehand but couldn't find anything obvious. |
Beta Was this translation helpful? Give feedback.
-
Unfortunately all of these options but the fourth option would change the meaning of existing code in potentially breaking ways. Even the last option of the initializer preferring a bulk initialization method could mean that the compiler could start favoring an existing method. The fourth option sounds interesting, a way to disable collection initializers. That would have to be driven by a new attribute. And maybe that could be combined with the fifth option so that the compiler would still naturally favor the existing |
Beta Was this translation helpful? Give feedback.
-
In the interim it'd probably be better to include a helper method to initialize in bulk and educate users to its use. Something like: var seq = Seq.Of(1, 2, 3, 4); |
Beta Was this translation helpful? Give feedback.
-
That already exists, and that's the documented way of construction: using static LanguageExt.Prelude;
...
var xs = Seq(1, 2, 3, 4); But, users of popular libraries are going to assume that the C# standard way of initialising collections will work and are surprised when they don't (to be honest, I hadn't given it a second though because I'd never used that feature of C# before). It shouldn't be the case that the language just co-opts methods without consideration for the scope of the problem. I didn't follow the original proposal, but it seems crazy to me that no-one considered immutable collections. I realise it's a done deal now and there's no way of going back, but we should have some options here. Option 4 from above would be absolutely fine, and I would hope the least amount of work to implement. |
Beta Was this translation helpful? Give feedback.
-
Keep in mind that collection initializers were added to C# in version 3.0 in 2007, while .Net immutable collections only came out in 2013. (The idea of immutable collections in general is of course much older, but I think they weren't commonly used in C# back then.) |
Beta Was this translation helpful? Give feedback.
-
I have started a proposal around the opt-out attribute |
Beta Was this translation helpful? Give feedback.
-
Note that .NET's immutable collections avoid this by having a private constructor, and defining builders / factory methods instead |
Beta Was this translation helpful? Give feedback.
-
Which doesn't work for structs. In language-ext all immutable collection types (Arr, HashMap, HashSet, Lst, Map, Que, Seq, Set, and Stck) are structs (with a I am in no way suggesting that structs are the biggest problem here. Clearly, my usage of them to protect against |
Beta Was this translation helpful? Give feedback.
-
That library can provide an analyzer to catch this issue and to gently guide users to use the correct patterns they need |
Beta Was this translation helpful? Give feedback.
-
Which is exactly how Roslyn does it, right? :) Not sure about Immutable collections though. Yeah - if there's a request for a language solution, which can be solved by Analyzers, it's like an additional -100 points for the request (I'd assume). |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Collection initialisers look for the
Add
method on a type so that they can repeatedly callAdd
to initialise a collection. This is problematic for immutable collections that have a default constructor (or are structs, which is what I use in language-ext).Example:
The following will result in an empty collection:
It seems to me that the collection initialiser functionality could use one of the following strategies:
Add
functions that return avoid
Add
functions that return a type that isn't the same as the one being constructedAdd
is the same as the type being constructed and foldreturn this
and immutable typesIEnumerable<A>
and use that instead of repeatedly callingAdd
(which feels like it would have been a better solution in the first place, because then the type can optimise how it constructs from a multi-item sequence).Right now the behaviour is unexpected and I've had users of my library reporting it as an issue.
Beta Was this translation helpful? Give feedback.
All reactions