有没有办法处理任何类型的集合,而不是仅仅依赖于Array,List等?

时间:2015-06-25 15:26:08

标签: c# performance collections

此示例适用于名为“WriteLines”的方法,该方法接受一个字符串数组并将它们添加到异步文件编写器中。它很有用,但我很好奇是否有一种有趣的方法来支持-any-字符串集合,而不是依靠程序员转换为数组。

我想出了类似的东西:

public void AddLines(IEnumerable<string> lines)
{
    // grab the queue
    lock (_queue)
    {
        // loop through the collection and enqueue each line
        for (int i = 0, count = lines.Count(); i < count; i++)
        {
            _queue.Enqueue(lines.ElementAt(i));
        }
    }
    // notify the thread it has work to do.
    _hasNewItems.Set();
}

这似乎有用,但我不知道它有任何性能影响,或任何逻辑含义(订单会发生什么?我认为这将允许甚至无序集合工作,例如HashSet)。

有没有更可接受的方法来实现这一目标?

2 个答案:

答案 0 :(得分:8)

您已通过IEnumerable<string> - 这意味着您可以对其进行迭代。哎呀,甚至还有特别的语言功能 - foreach

foreach (string line in lines)
{
    _queue.Enqueue(line);
}

与现有方法不同,这只会迭代序列一次。您当前的代码将根据底层实现的不同而有所不同 - 在某些情况下Count()ElementAt已经过优化,但在某些情况下它们并非如此。如果使用迭代器块并记录日志,则可以非常轻松地看到这一点:

public IEnumerable<string> GetItems()
{
    Console.WriteLine("yielding a");
    yield return "a";
    Console.WriteLine("yielding b");
    yield return "b";
    Console.WriteLine("yielding c");
    yield return "c";
}

尝试使用当前的实现调用AddLines(GetItems()),然后查看控制台......

答案 1 :(得分:0)

由于您使用的是线程,因此添加此答案时,请使用ConcurrentQueue,如下所示:

// the provider method
// _queue = new BlockingCollection<string>()
public void AddLines(IEnumerable<string> lines)
{
   foreach (var line in lines)
   {
     _queue.Add(line);
   }
}

不需要锁定,并允许多个使用者和提供者,因为我们标记了添加的每个元素。

消费者基本上只需做var workitem = _queue.Take();