How to turn ICollection <T> into IReadOnlyCollection <T>?

When I have an ICollection<T> variable in C #, I cannot pass it to a function waiting for IReadOnlyCollection<T> :

 public void Foo() { ICollection<int> data = new List<int>(); // Bar(data); // Not allowed: Cannot implicitly cast ICollection<int> to IReadOnlyCollection<int> Bar(data.ToList()); // Works, since List<T> implements IReadOnlyCollection<T> } public void Bar(IReadOnlyCollection<int> data) { if (data.Count == 1) { /* ... */ } // ... } 

Apparently, the problem is that ICollection<T> not inherited from IReadOnlyCollection<T> - but why? ICollection<T> should be a full functional set of IReadOnlyCollection<T> plus functions that modify the collection.

And what is the best solution for passing arguments?

On the one hand, since I do not want to change the collection in Bar , and I just need to count and IReadOnlyCollection over the collection, I would like to require IReadOnlyCollection .

On the other hand, I do not want to create a new list object every time I call this function.

+5
source share
2 answers

There is no standard AFAIK solution, but it is not difficult to do as if

 public static class MyExtensions { public static IReadOnlyCollection<T> AsReadOnly<T>(this ICollection<T> source) { if (source == null) throw new ArgumentNullException("source"); return source as IReadOnlyCollection<T> ?? new ReadOnlyCollectionAdapter<T>(source); } sealed class ReadOnlyCollectionAdapter<T> : IReadOnlyCollection<T> { ICollection<T> source; public ReadOnlyCollectionAdapter(ICollection<T> source) { this.source = source; } public int Count { get { return source.Count; } } public IEnumerator<T> GetEnumerator() { return source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } 

And then use it as follows

 Bar(data.AsReadOnly()); 
+3
source

You can pretty trivially create a class that makes up ICollection<T> when implementing IReadOnlyCollection<T> . You can also create an extension method to perform the wrapping (and thus allow type type inference):

 public class ReadOnlyCollectionWrapper<T> : IReadOnlyCollection<T> { private ICollection<T> collection; public ReadOnlyCollectionWrapper(ICollection<T> collection) { this.collection = collection; } public int Count { get { return collection.Count; } } public IEnumerator<T> GetEnumerator() { return collection.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return collection.GetEnumerator(); } } public static class ReadOnlyCollectionWrapper { public static IReadOnlyCollection<T> AsReadOnly<T>(this ICollection<T> collection) { return new ReadOnlyCollectionWrapper<T>(collection); } } 
+5
source

Source: https://habr.com/ru/post/1238666/


All Articles