为什么ConcurrentBag< T>实现ICollection< T>吗? [英] Why doesn't ConcurrentBag<T> implement ICollection<T>?

查看:67
本文介绍了为什么ConcurrentBag< T>实现ICollection< T>吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个采用IList<>并向其中添加内容的方法.在某些情况下,我想通过 ConcurrentBag 't实现IList<>或ICollection<>,仅实现非通用 ICollection ,它没有Add方法.

I have a method which takes an IList<> and adds stuff to it. I would like to pass it a ConcurrentBag in some cases, but it doesn't implement IList<> or ICollection<>, only the non-generic ICollection, which doesn't have an Add method.

现在,我明白了为什么它不能(也许)实现IList的原因-它不是一个有序的集合,因此拥有索引器对它没有任何意义.但是我没有看到任何 ICollection<> 的问题方法.

Now, I see why it can't (maybe) implement IList - it's not an ordered collection so it won't make sense for it to have an indexer. But I don't see an issue with any of the ICollection<> methods.

那为什么呢?而且-在.NET中是否存在一个线程安全的集合,它实现了更可靠的接口?

So, why? And, also - is there a thread-safe collection in .NET that does implement more robust interfaces?

推荐答案

List< T> 不是并发的,因此它可以实现 ICollection< T> 这对方法包含 Add .如果 Contains 返回 false ,则可以安全地调用 Add ,知道它将成功.

A List<T> is not concurrent and so it can implement ICollection<T> which gives you the pair of methods Contains and Add. If Contains returns false you can safely call Add knowing it will succeed.

ConcurrentBag< T> 是并发的,因此它不能实现 ICollection< T> ,因为答案 Contains 返回可能被无效.您致电添加的时间.相反,它实现了 IProducerConsumerCollection< T> ,该方法提供了一种单独的方法 TryAdd ,该方法可以同时执行 Contains Add

A ConcurrentBag<T> is concurrent and so it cannot implement ICollection<T> because the answer Contains returns might be invalid by the time you call Add. Instead it implements IProducerConsumerCollection<T> which provides the single method TryAdd that does the work of both Contains and Add.

很不幸,您希望对两个都是集合但不共享公共接口的东西进行操作.有很多方法可以解决此问题,但是当API与这些API相似时,我的首选方法是为两个接口都提供方法重载,然后使用lambda表达式来制作使用自己的方法对每个接口执行相同操作的委托.然后,您可以使用该委托代替执行几乎常见操作的位置.

So unfortunately you desire to operate on two things that are both collections but don't share a common interface. There are many ways to solve this problem but my preferred approach when the API is as similar as these are is to provide method overloads for both interfaces and then use lambda expressions to craft delegates that perform the same operation for each interface using their own methods. Then you can use that delegate in place of where you would have performed the almost common operation.

这是一个简单的例子:

public class Processor
{
    /// <summary>
    /// Process a traditional collection.
    /// </summary>
    /// <param name="collection">The collection.</param>
    public void Process(ICollection<string> collection)
    {
        Process(item =>
            {
                if (collection.Contains(item))
                    return false;
                collection.Add(item);
                return true;
            });
    }

    /// <summary>
    /// Process a concurrent collection.
    /// </summary>
    /// <param name="collection">The collection.</param>
    public void Process(IProducerConsumerCollection<string> collection)
    {
        Process(item => collection.TryAdd(item));
    }

    /// <summary>
    /// Common processing.
    /// </summary>
    /// <param name="addFunc">A func to add the item to a collection</param>
    private void Process(Func<string, bool> addFunc)
    {
        var item = "new item";
        if (!addFunc(item))
            throw new InvalidOperationException("duplicate item");
    }
}

这篇关于为什么ConcurrentBag&lt; T&gt;实现ICollection&lt; T&gt;吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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