有没有一种方法可以处理任何类型的集合,而不是仅仅依赖Array、List等

本文关键字:集合 依赖 List Array 类型 一种 方法 任何 处理 有没有 | 更新日期: 2023-09-27 17:59:38

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

我想出了这样的东西:

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

有没有一种更容易被接受的方法来实现这一点?

有没有一种方法可以处理任何类型的集合,而不是仅仅依赖Array、List等

您已经被传递了一个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()),然后查看控制台。。。

由于您使用的是线程,因此也要添加此答案,请使用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();