[英]How to turn ICollection<T> into IReadOnlyCollection<T>?
When I have a variable of ICollection<T>
in C#, I cannot pass it to a function that expects an IReadOnlyCollection<T>
:当我在 C# 中有一个
ICollection<T>
变量时,我无法将它传递给需要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>
does not inherit from IReadOnlyCollection<T>
- but why?显然问题是
ICollection<T>
没有继承自IReadOnlyCollection<T>
- 但为什么呢? ICollection<T>
should be the full functional set of IReadOnlyCollection<T>
plus the functions that modify the collection. ICollection<T>
应该是IReadOnlyCollection<T>
的完整功能集加上修改集合的函数。
And what is the best solution to pass the arguments?传递参数的最佳解决方案是什么?
On the one hand, since I don't want to alter the collection in Bar
and just need the count and iterate over the collection, I'd like to require an IReadOnlyCollection
.一方面,由于我不想更改
Bar
中的集合,只需要对集合进行计数和迭代,因此我想要一个IReadOnlyCollection
。
On the other hand, I don't want to create a new list object every time I call that function.另一方面,我不想每次调用该函数时都创建一个新的列表对象。
There is no standard solution AFAIK, but it's not hard to make your own like this没有标准解决方案 AFAIK,但像这样制作自己的解决方案并不难
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>
{
readonly ICollection<T> source;
public ReadOnlyCollectionAdapter(ICollection<T> source) => this.source = source;
public int Count => source.Count;
public IEnumerator<T> GetEnumerator() => source.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
And then use it as follows然后按如下方式使用
Bar(data.AsReadOnly());
You can pretty trivially create a class that composes an ICollection<T>
while implementing IReadOnlyCollection<T>
.在实现
IReadOnlyCollection<T>
> 时,您可以非常简单地创建一个组成ICollection<T>
的类。 You can also create an extension method to do the wrapping (and thus allow for generic 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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.