IList<T>和 IReadOnlyList<T> [英] IList&lt;T&gt; and IReadOnlyList&lt;T&gt;

查看:32
本文介绍了IList<T>和 IReadOnlyList<T>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If I have a method that requires a parameter that,

  • 有一个 Count 属性
  • 有一个整数索引器(仅限获取)

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

What should the type of this parameter be? I would choose IList<T> before .NET 4.5 since there was no other indexable collection interface for this and arrays implement it, which is a big plus.

但是 .NET 4.5 引入了新的 IReadOnlyList 接口,我希望我的方法也支持它.如何在不违反 DRY 等基本原则的情况下编写此方法以同时支持 IListIReadOnlyList?

But .NET 4.5 introduces the new IReadOnlyList<T> interface and I want my method to support that, too. How can I write this method to support both IList<T> and IReadOnlyList<T> without violating the basic principles like DRY?

编辑:丹尼尔的回答给了我一些想法:

Edit: Daniel's answer gave me some ideas:

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 并提供这样的帮助程序:


Edit 2: Or I could just accept an IReadOnlyList<T> and provide a helper like this:

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

Then I could call it like Foo(list.AsReadOnly())

编辑 3:数组实现了 IListIReadOnlyListList 也是如此. 类.这使得很难找到实现 IList 而不是 IReadOnlyList 的类.

Edit 3: Arrays implement both IList<T> and IReadOnlyList<T>, so does the List<T> class. This makes it pretty rare to find a class that implements IList<T> but not IReadOnlyList<T>.

推荐答案

你在这里走运了.IList 没有实现 IReadOnlyList.List 确实实现了这两个接口,但我认为这不是您想要的.

You are out of luck here. IList<T> doesn't implement IReadOnlyList<T>. List<T> does implement both interfaces, but I think that's not what you want.

但是,您可以使用 LINQ:

However, you can use LINQ:

  • Count() 扩展方法在内部检查实例实际上是否是一个集合,然后使用 Count 属性.
  • ElementAt() 扩展方法在内部检查实例是否实际上是一个列表,然后使用索引器.
  • The Count() extension method internally checks whether the instance in fact is a collection and then uses the Count property.
  • The ElementAt() extension method internally checks whether the instance in fact is a list and than uses the indexer.

这篇关于IList<T>和 IReadOnlyList<T>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆