C# 返回一个ICollection<;T>;作为IReadOnlyCollection<;T>;?

C# 返回一个ICollection<;T>;作为IReadOnlyCollection<;T>;?,c#,.net,collections,ienumerable,readonly-collection,C#,.net,Collections,Ienumerable,Readonly Collection,我有一个类型为ICollection的字段。有没有一种简单的方法使它成为只读的 注意,ReadOnlyCollection类采用了一个IList,我正在寻找一种方法来反转ICollection,并确保用户不能更改集合 使用AsEnumerableex.方法并不能保证这一点,因为它可以转换回其原始类型,也可以是List,ReadOnlyCollection实际上是一个只读列表,我一直认为这有点奇怪 这就是说,ICollection是一个非常简单的接口,实现真正的ReadOnlyCollection

我有一个类型为
ICollection
的字段。有没有一种简单的方法使它成为只读的

注意,
ReadOnlyCollection
类采用了一个
IList
,我正在寻找一种方法来反转
ICollection
,并确保用户不能更改集合


使用
AsEnumerable
ex.方法并不能保证这一点,因为它可以转换回其原始类型,也可以是
List

ReadOnlyCollection
实际上是一个只读列表,我一直认为这有点奇怪

这就是说,
ICollection
是一个非常简单的接口,实现真正的
ReadOnlyCollection

公共类TrueReadOnlyCollection:ICollection、DirectAdonlyCollection
{
私人收藏(原件);;
公共TrueReadOnlyCollection(ICollection原件)
{
_原件=原件;
}
公共作废新增(T项)
{
抛出新的NotSupportedException();
}
公共空间清除()
{
抛出新的NotSupportedException();
}
公共布尔包含(T项)
{
退货-原件包含(项目);
}
public void CopyTo(T[]数组,int arrayIndex)
{
_原件.CopyTo(数组,数组索引);
}
公共整数计数
{
获取{return\u original.Count;}
}
公共图书馆是只读的
{
获取{return true;}
}
公共布尔删除(T项)
{
抛出新的NotSupportedException();
}
公共IEnumerator GetEnumerator()
{
foreach(原版)
{
收益率t;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
}

请注意,在.NET 4.5中,也有实际的只读接口来支持新的接口变化特性,因此,如果您正在执行上述操作,则最好同时实现

ICollection implements IEnumerable,因此我认为您可以只执行
.ToList().AsReadOnly()
。但正如Peter Duniho所指出的,这会创建原始集合的副本,因此副本中不会显示对其的任何更改,尽管看起来这可能是您想要的。

如果您对原始集合的副本感到满意,即返回一个不会反映将来对原始集合所做更改的对象,那么我认为只需将集合复制到一个数组并返回它就可以了(如果确实需要,请使用ReadOnlyCollection进行包装,但此时可能并非绝对必要)。如果确实希望返回的集合反映对原始集合的未来更改,请参阅我发布的答案。正如您所注意的,这会创建所有内容的额外副本,这对于大型集合来说可能是一个主要问题。
public class TrueReadOnlyCollection<T> : ICollection<T>, IReadOnlyCollection<T>
{
    private ICollection<T> _original;

    public TrueReadOnlyCollection(ICollection<T> original)
    {
        _original = original;
    }

    public void Add(T item)
    {
        throw new NotSupportedException();
    }

    public void Clear()
    {
        throw new NotSupportedException();
    }

    public bool Contains(T item)
    {
        return _original.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        _original.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return _original.Count; }
    }

    public bool IsReadOnly
    {
        get { return true; }
    }

    public bool Remove(T item)
    {
        throw new NotSupportedException();
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (T t in _original)
        {
            yield return t;
        }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}