如果我有一个方法需要一个参数,

  • 具有Count属性
  • 具有整数索引器(仅获取)

  • 此参数的类型应该是什么?我会在.NET 4.5之前选择IList<T>,因为没有其他可索引的集合接口(interface),并且数组可以实现它,这是一个很大的优点。

    但是.NET 4.5引入了新的IReadOnlyList<T>接口(interface),我也希望我的方法也支持该接口(interface)。如何编写此方法以同时支持IList<T>IReadOnlyList<T>而又不违反DRY等基本原理?

    编辑:Daniel的回答给了我一些想法:
    public void Foo<T>(IList<T> list)
        => Foo(list, list.Count, (c, i) => c[i]);
    
    public void Foo<T>(IReadOnlyList<T> list)
        => Foo(list, list.Count, (c, i) => c[i]);
    
    private void Foo<TList, TItem>(
        TList list, int count, Func<TList, int, TItem> indexer)
        where TList : IEnumerable<TItem>
    {
        // Stuff
    }
    

    编辑2:或我也可以接受IReadOnlyList<T>并提供这样的帮助器:
    public static class CollectionEx
    {
        public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> list)
        {
            if (list == null)
                throw new ArgumentNullException(nameof(list));
    
            return list as IReadOnlyList<T> ?? new ReadOnlyWrapper<T>(list);
        }
    
        private sealed class ReadOnlyWrapper<T> : IReadOnlyList<T>
        {
            private readonly IList<T> _list;
    
            public ReadOnlyWrapper(IList<T> list) => _list = list;
    
            public int Count => _list.Count;
    
            public T this[int index] => _list[index];
    
            public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
    
            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
        }
    }
    

    然后我可以像Foo(list.AsReadOnly())这样称呼它

    编辑3:数组同时实现IList<T>IReadOnlyList<T>List<T>类也实现。这使得很难找到实现IList<T>而不是IReadOnlyList<T>的类。

    最佳答案

    您真不走运。 IList<T>没有实现IReadOnlyList<T>List<T>确实实现了两个接口(interface),但我认为这不是您想要的。

    但是,您可以使用LINQ:

  • Count()扩展方法在内部检查该实例是否实际上是一个集合,然后使用Count属性。
  • ElementAt()扩展方法在内部检查该实例是否实际上是列表,然后使用索引器。
  • 关于c# - IList <T>和IReadOnlyList <T>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12838122/

    10-09 06:12