-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Add common ancestor for ICollection<T> and IReadOnlyCollection<T> #105180
Comments
Tagging subscribers to this area: @dotnet/area-system-collections |
@huoyaoyuan No need to be quite so dismissive. I did search for similar issues. I simply missed #31001, because it proposed a very different solution and wasn't well-indexed. In the case of the #31001, the proposal is that That said, I see that moving the singular I never claimed to be perfect. Though, with due respect, the response to this rather obvious issue has also been less than perfect. It has been lingering (and snowballing) for about 20 years now, since shortly after generics were introduced in 2005. It might be nice to see a resolution in (maybe?) the next decade. 😄 Until then, I'll continue doing what I have since pattern matching was introduced. I constrain to |
There's no perfect solution. So any response will be in kind.
Improvements have been made (esp. in hte .net 9 timeframe). These are the best possible steps given the enormous importance of compatibility in the .net ecosystem. |
@CyrusNajmabadi has there been any discussions around potentially creating an interface that represents just the availability of a I know it would similarly introduce breaking changes, but just wondering if the team has considered that (instead of having it be part of |
@CyrusNajmabadi Thank you for taking the time to read this discussion and offer some feedback. I'd gladly settle for an imperfect solution. The problem has continued to compound for a very long time now. After all that time, I'd happily settle for a "bandage" that makes the issue less cumbersome to work around. Perhaps, a well-documented extension method for This would at least lighten the lifting load when I am inevitably forced to use Or maybe it would help if a common ancestor interface (for the two collection interfaces) were added? Even one without any members could be useful (providing it is descended from The new interface would at least provide a more restrictive constraint and/or parameter type. The name of the interface would advertise its intent. The extension method would handle the plumbing and enforcement (admittedly at run-time instead of compile-time). With more commitment, perhaps the compiler could help with some syntactic sugar? Anyhow, these are just a few ideas, off the top of my head ideas. None of them introduce breaking changes. Any of them would at least slightly improve the situation. I feel certain smarter people than I could come up with even better ideas. That said, my original point stands, taking nearly 20 years (and counting) to address the issue is not a good look. At this rate, I'm not sure C# will still be relevant by the time help arrives 😄 |
Background and motivation
Often, I find myself designing methods or classes that can act on any readable and countable collection. When doing so, it would be advantageous to add a constraint that allows all such collections to be consumed. Ideally, this constraint would encompass both
ICollection<T>
andIReadOnlyCollection<T>
.Unfortunately, this is not currently possible. These two interfaces both share the requisite
Count
property andGetEnumerator()
method. Unfortunately, they do not share a common ancestor interface that advertises these capabilities.Admittedly, the common
IEnumerable<T>
interface comes close. However, there are often advantages to knowing the size of the collection (Count
) prior to its iteration. This is the specific use case considered by this issue.I propose adding a common ancestor interface,, perhaps
IReadableCollection<T>
.While the current
IReadOnlyCollection<T>
andIReadableCollection<T>
would be nearly identical, their purpose would be significantly different. The former asserts that the collection cannot be written. The latter does not make this same assertion.Regrettably, the historical lack of this interface has also led to a proliferation of
ReadOnlyXXX<T>
classes that must implement bothICollection<T>
andIReadOnlyCollection<T>
. It is a shame that these classes must implement, hide, and throw exceptions for the properties and methods related to writing. However, I do understand, given .NET's evolutionary history, why this was necessary.While adding this new common ancestor cannot fix the past, and it can help mitigate the continuing proliferation of this issue.
API Proposal
API Usage
Alternative Designs
Originally, a cleaner design might have also moved the
IsReadOnly
property toIReadableCollection<T>
and eliminated the need for theIReadOnlyCollection<T>
interface. Unfortunately, at this point, that would likely involve breaking changes.Risks
Since both of the derived interfaces already implement the necessary property
Count
and methodGetEnumerator()
for the proposed ancestorIReadableCollection<T>
, the risks should be minimal.The risk in not implementing it is that developers will continue to "creatively" work around this issue.
The text was updated successfully, but these errors were encountered: