如何实例化字典中特定数量的项目?

时间:2018-10-30 15:14:05

标签: c# dictionary

我正在尝试声明具有特定数量项的Dictionary<Task>,我尝试过:

private Dictionary<Task, CancellationToken> bots = 
        new Dictionary<Task, CancellationToken>(new Task[9], new CancellationToken[9]);

这将返回以下错误:

  

您不能从“ System.Threading.Tasks.Task []”转换为“ System.Collections.Generic.IDictionary”

如果我在List中这样做,那么一切正常:

private List<Task> bots = new List<Task>(new Task[9]);

3 个答案:

答案 0 :(得分:1)

错误显示您正在尝试不存在的东西。

其中一个重写词典构造函数接受

public Dictionary(IDictionary<TKey, TValue> dictionary);
public Dictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer);

您提供的参数都不正确。 您输入的第一个输入是Task [],第二个输入是CancellationToken []

您应该创建一个IDictionary实现,通常是一个Dictionary,然后将其传递给它。

var example1Original = new Dictionary<Task, CancellationToken>();
example1Original.Add(new Task(DoWork), new CancellationToken());
example1Original.Add(new Task(DoWork), new CancellationToken());
// and more (This procedure can be shorten using a loop)

var example1Result = new Dictionary<Task, CancellationToken>(example1Original);

如您所见,我们已成功将变量传递到Dictionary构造函数中,这是可能的,因为Dictionary实现了IDictionary,如我们在此处看到的 Declaration of Dictionary<TKey, TValue>

但是最后一行实际上是多余的,因为是的,我们可以通过它,但是我们不需要。因为我们填充的example1Original已经是我们要使用的字典。

所以这引出了一个问题,为什么Dictionary构造函数首先将其包含。这就引出了我们最初的说法,即IDictionary可以具有可以通过的多种实现。

这里有一些IDictionary实现 IDictionary<TKey, TValue> implementations
(图片是使用ILSpy从mscorlib.dll拍摄的)

实际上,您的问题是,我该如何用Task和Cancellation令牌的新实例填充我的Dictionary。

这可以通过以下方式完成:

  1. 之前的上述代码。 (并通过循环进一步缩短)
  2. 或者以较短的方式使用出色的语言功能。

我们将要使用的功能

  • System.Linq.Enumerable.Range-生成指定范围内的整数序列。
  • System.Linq.Enumerable.Select-将序列的每个元素投影为新形式。
  • 接口的功能-用于允许我们使用ToDictionary扩展方法。
  • System.Linq.Enumrable.ToDictionary()-使用IEnumerable并生成字典的扩展方法

Enumerable.ToDictionary-由于IDictionary本身实现IEnumerable,因此我们可以使用以下ToDictionary扩展方法

System.Linq 名称空间中的

扩展方法

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector);

如果我们将使用这些功能,我们可以构建以下内容以生成我们的字典。

var kvpOfTaskCancellation = Enumerable.Range(0, 9) // Generates Enumerable integers sequence.
    .Select(i => new KeyValuePair<Task, CancellationToken>(new Task(DoWork), new CancellationToken())) // Iterating and projecting every elements inside the previous generated sequence.
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Mapping each iteration from the previous line KeyValuePair objects to the Dictionary Key and Value.

还可以缩短为以下内容

var kvpOfTaskCancellation2 = Enumerable.Range(0, 9)
    .ToDictionary(kvp => new Task(DoWork), kvp => new CancellationToken());

如果您想要一个新的“任务和取消”令牌,这一切都可以。

但是但是,如果您已经有大量的Tasks和CancellationTokens集合,并且想要从中生成一个Dictionary,那么您可以执行以下操作:

var tasks = new Task[3];
// I'm assuming the tasks already been populated
tasks.ToDictionary(kvp => kvp, kvp => new CancellationToken());

但是如果您还具有CancellationToken数组,则可以使用以下内容:

var tasks = new Task[3];
var cancellationsTokens = new CancellationToken[9];
// I'm assuming tasks and cancellationToken array already been filled.
Enumerable.Range(0, tasks.Length)
    .Select(i => new KeyValuePair<Task, CancellationToken>(tasks[i], cancellationsTokens[i]))
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

答案 1 :(得分:0)

Task的未初始化数组仅包含null元素,并且不能将null作为字典项的键,但是通常,如果您已初始化数组,则可以使用Linq将字典与这些数组配合使用:

var dictionary = (from token in new CancellationToken[9]
                 from task in initializedTaskArray
                 select (task, token)
                 )
                 .ToDictionary(x => x.task, x => x.token);

答案 2 :(得分:-1)

您需要执行以下操作:

private Dictionary<Task, CancellationToken> bots = new Dictionary<Task, CancellationToken>() {
    { new Task(), new CancellationToken() },
    { new Task(), new CancellationToken() },
    ...
}