Repository navigation
Closed
Labels
Milestone
Description
From #88093 (comment):
We should revisit this.
Lines 93 to 96 in e5ddc6c
/// The reason we don't copy anything other than for well-known types is that a malicious interface /// implementation of <see cref="ICollection{T}"/> could hold on to the array when its <see cref="ICollection{T}.CopyTo"/> /// method is called. If the array it holds onto underlies an <see cref="ImmutableArray{T}"/>, it could violate /// immutability by modifying the array.
That logic, while well-meaning, isn't worth making the implementations slower. If code wants to get at the underlying array of an ImmutableArray, there are easier ways, including a now fully supported public API.
The comment that triggered the conversation #88093 (comment):
The custom
ToArrayimplementation is slower, because it usesCopyToonly for collections that implementIList<T>, while bothKeyCollectionandValueCollectiondon't. They do implementICollection<T>which is used by LINQ.
Lines 158 to 164 in c06d77a
| if (!sequence.TryCopyTo(array, 0)) | |
| { | |
| int i = 0; | |
| foreach (T item in sequence) | |
| { | |
| Requires.Argument(i < count); | |
| array[i++] = item; |
Line 106 in c06d77a
| if (sequence is IList<T>) |
| public sealed partial class KeyCollection : System.Collections.Generic.ICollection<TKey>, System.Collections.Generic.IEnumerable<TKey>, System.Collections.Generic.IReadOnlyCollection<TKey>, System.Collections.ICollection, System.Collections.IEnumerable |
| public sealed partial class ValueCollection : System.Collections.Generic.ICollection<TValue>, System.Collections.Generic.IEnumerable<TValue>, System.Collections.Generic.IReadOnlyCollection<TValue>, System.Collections.ICollection, System.Collections.IEnumerable |
cc @stephentoub
Activity
prozolic commentedon Mar 6, 2026
Is this issue still open for contributions? I'd like to work on a fix if no one is actively assigned to it.
I'm planning to make the following changes to
ImmutableExtensions.TryCopyTo.IList<T>toICollection<T>List<T>,T[], orImmutableArray<T>, fall back toICollection<T>.CopyTo#if NET) to ensure the sequence is not an array before falling back toICollection<T>.CopyToto avoid issues with array covariance in .NET Frameworkadamsitnik commentedon Mar 6, 2026
Hi @prozolic
Yes, it's still opened for contributions. Please make sure you benchmark you changes locally when working on it: https://github.com/dotnet/performance/blob/main/docs/benchmarking-workflow-dotnet-runtime.md
prozolic commentedon Mar 6, 2026
Thank you @adamsitnik!
The benchmark result measured locally are as follows.
Benchmark
source
adamsitnik commentedon Mar 7, 2026
Provided benchmark results look good to me. There is a regression, but it's small compared to gains for the other codepaths.
prozolic commentedon Mar 8, 2026
Thank you for your confirmation.
I've submitted a #125304 with this fix.
Use ICollection<T> check instead of IList<T> in TryCopyTo (#125304)
prozolic commentedon Oct 21, 2026
@jkotas I forgot to add
Closes #88181to the PR description, so this issue was not linked to the PR and was not closed. Could you please close this issue?jkotas commentedon Oct 21, 2026
Fixed by #125304