Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ICollection<T> usage to IReadOnlyCollection<T> where applicable #101469

Merged
merged 2 commits into from
Apr 25, 2024

Conversation

stephentoub
Copy link
Member

Anywhere we're casting to ICollection<T> just to use its Count, we can instead now cast to IReadOnlyCollection<T>, as the former inherits the latter as of .NET 9. This expands the set of types that can light-up with the check; in a couple of places it also lets us remove what would then be a duplicative check. We can do the same for IList<T> and IReadOnlyList<T>.

While dispatch via the DIM could result in an extra interface dispatch for types that weren't previously implementing the read-only interface, a) our collection types already implement both, and b) these cases all represent fast paths where the extra savings from the faster path should more than make up for additional call overheads. I audited for anywhere we were missing explicit implementations and added in a few corner-cases.

Anywhere we're casting to `ICollection<T>` just to use its `Count`, we can instead now cast to `IReadOnlyCollection<T>`, as the former inherits the latter as of .NET 9. This expands the set of types that can light-up with the check; in a couple of places it also lets us remove what would then be a duplicative check. We can do the same for `IList<T>` and `IReadOnlyList<T>`.

While dispatch via the DIM could result in an extra interface dispatch for types that weren't previously implementing the read-only interface, a) our collection types already implement both, and b) these cases all represent fast paths where the extra savings from the faster path should more than make up for additional call overheads. I audited for anywhere we were missing explicit implementations and added a few corner-cases in.
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 24, 2024
@stephentoub stephentoub added area-System.Collections and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Apr 24, 2024
@stephentoub stephentoub added this to the 9.0.0 milestone Apr 24, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-collections
See info in area-owners.md if you want to be subscribed.

@mphelt
Copy link
Contributor

mphelt commented Apr 25, 2024

Shouldn't ReadOnlyCollection also be added to this PR to change it's backing field from IList to IROL?

@eiriktsarpalis
Copy link
Member

Shouldn't ReadOnlyCollection also be added to this PR to change it's backing field from IList to IROL?

It shouldn't matter much -- the constructor itself accepts IList and we can't change that.

@mphelt
Copy link
Contributor

mphelt commented Apr 25, 2024

Shouldn't ReadOnlyCollection also be added to this PR to change it's backing field from IList to IROL?

It shouldn't matter much -- the constructor itself accepts IList and we can't change that.

I meant changing the constructor along with the backing field. If constructor can't be changed due to potential breaking changes, then changing the backing field allows to create a factory method instead.

@eiriktsarpalis
Copy link
Member

I meant changing the constructor along with the backing field. If constructor can't be changed due to potential breaking changes, then changing the backing field allows to create a factory method instead.

I don't think it would be possible even if we considered new API. If you take a closer look at the implementation you'll see that it meaningfully relies on the underlying collection being an IList<T>, for example the indexer and CopyTo methods. IReadOnlyCollection<T> is a very simple interface -- it's just an IEnumerable<T> with a Count property.

@stephentoub stephentoub merged commit e92b7d0 into dotnet:main Apr 25, 2024
142 of 147 checks passed
@stephentoub stephentoub deleted the useirocc branch April 25, 2024 20:41
jkotas added a commit to jkotas/runtime that referenced this pull request Apr 27, 2024
jkotas added a commit that referenced this pull request Apr 27, 2024
…y collection interfaces (#95830)" (#101644)

* Revert "Update ICollection<T> usage to IReadOnlyCollection<T> where applicable (#101469)"

This reverts commit e92b7d0.

* Revert "Make mutable generic collection interfaces implement read-only collection interfaces (#95830)"

This reverts commit a2bd583.

* Update src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs
matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
dotnet#101469)

Anywhere we're casting to `ICollection<T>` just to use its `Count`, we can instead now cast to `IReadOnlyCollection<T>`, as the former inherits the latter as of .NET 9. This expands the set of types that can light-up with the check; in a couple of places it also lets us remove what would then be a duplicative check. We can do the same for `IList<T>` and `IReadOnlyList<T>`.

While dispatch via the DIM could result in an extra interface dispatch for types that weren't previously implementing the read-only interface, a) our collection types already implement both, and b) these cases all represent fast paths where the extra savings from the faster path should more than make up for additional call overheads. I audited for anywhere we were missing explicit implementations and added a few corner-cases in.
matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…y collection interfaces (dotnet#95830)" (dotnet#101644)

* Revert "Update ICollection<T> usage to IReadOnlyCollection<T> where applicable (dotnet#101469)"

This reverts commit e92b7d0.

* Revert "Make mutable generic collection interfaces implement read-only collection interfaces (dotnet#95830)"

This reverts commit a2bd583.

* Update src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
dotnet#101469)

Anywhere we're casting to `ICollection<T>` just to use its `Count`, we can instead now cast to `IReadOnlyCollection<T>`, as the former inherits the latter as of .NET 9. This expands the set of types that can light-up with the check; in a couple of places it also lets us remove what would then be a duplicative check. We can do the same for `IList<T>` and `IReadOnlyList<T>`.

While dispatch via the DIM could result in an extra interface dispatch for types that weren't previously implementing the read-only interface, a) our collection types already implement both, and b) these cases all represent fast paths where the extra savings from the faster path should more than make up for additional call overheads. I audited for anywhere we were missing explicit implementations and added a few corner-cases in.
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…y collection interfaces (dotnet#95830)" (dotnet#101644)

* Revert "Update ICollection<T> usage to IReadOnlyCollection<T> where applicable (dotnet#101469)"

This reverts commit e92b7d0.

* Revert "Make mutable generic collection interfaces implement read-only collection interfaces (dotnet#95830)"

This reverts commit a2bd583.

* Update src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs
@github-actions github-actions bot locked and limited conversation to collaborators May 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants