c# - 如何将 ICollection<T> 转换为 IReadOnlyCollection<T>?

标签 c# icollection

当我有一个 ICollection<T> 的变量时在 C# 中,我无法将它传递给需要 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) { /* ... */ }
  // ...
}

显然问题是ICollection<T>不继承自 IReadOnlyCollection<T> - 但为什么? ICollection<T>应该是 IReadOnlyCollection<T> 的完整功能集加上修改集合的函数。

传递参数的最佳解决方案是什么?

一方面,因为我不想改变 Bar 中的集合只需要对集合进行计数和迭代,我想要一个 IReadOnlyCollection .

另一方面,我不想每次调用该函数时都创建一个新的列表对象。

最佳答案

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();
    }
}

然后如下使用

Bar(data.AsReadOnly());

关于c# - 如何将 ICollection<T> 转换为 IReadOnlyCollection<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34362316/

相关文章:

c# - 用于在 C# 中创建 MIDI 曲调的 API/库?

c# - return ICollection 比 List 有什么优势

c# - UserControl 元素由于其保护级别而无法访问

c# - .NET 正则表达式 : negate previous character for the first character in string

c# - 如何在引发另一个事件时引发一个事件?

c# - 将 LinqToSql 表绑定(bind)到 Repeater

C# 将对象转换为 List<object>

c# - 是否有一个术语可以互换地描述 C# 中的接口(interface)或抽象类?

c# - Array 没有实现 ICollection<T> 但可以赋值

c# - 如何清除() Entity Framework ICollection 中的所有元素?