ToArray()vs new JArray():将IEnumerable <t>转换为Collection <t>更有效

时间:2017-08-01 06:11:15

标签: c# linq json.net

我需要将IEnumerable<JToken>查询的LINQ结果转换为集合,以便我可以对其进行索引。现在基本上我发现有两种方法可以做到这一点。

我可以使用ToArray()将其转换为JToken[]

JToken[] arrElementValues = arrResults.Where(joResults => joResults["uResultId"]?.ToString() == arrTaskResults[intResult]["uResultId"]?.ToString() &&
                                       joResults["iElementId"]?.ToString() == strUniqueElementId && joResults["iContainerId"]?.ToString() == strContainerId).ToArray();

或者我可以将IEnumerable<JToken>传递给JArray()

IEnumerable<JToken> enmElementValues = arrResults.Where(joResults => joResults["uResultId"]?.ToString() == arrTaskResults[intResult]["uResultId"]?.ToString() &&
                                       joResults["iElementId"]?.ToString() == strUniqueElementId && joResults["iContainerId"]?.ToString() == strContainerId);

JArray arrElementValues = new JArray(enmElementValues);

那么哪种方法更好更有效?

3 个答案:

答案 0 :(得分:1)

您还可以对列表(IReadOnlyList)进行索引。在您的情况下,输入序列的长度是未知的,因此ToArray将使用与ToList中使用的代码类似的代码来增加存储枚举项的缓冲区随着项目数量的增加。最初,该列表将具有4个项目的容量。枚举第5项时,将创建两倍大小的新缓冲区,并将原始缓冲区复制到新缓冲区(不能在.NET中展开已分配的数组)。此过程将继续,直到枚举所有项目为止。

如果序列有10个项目,那么最终缓冲区将具有16个项目(4 * 2 * 2)的容量。使用ToList将使用此缓冲区返回一个列表,但使用ToArray将创建一个包含10个项目的新数组,并将缓冲区复制到缩小最终存储的阵列,以便没有多余的容量。

因此,使用ToListToArray相比,如果项目数量与容量4,8,16,32 ......之一不匹配,则使用较少的CPU(最终分配)被跳过)但可以使用更多内存(缓冲区中未使用的容量)。

使用JArray添加了评论中提到的其他语义,虽然它可能与ToListToArray的效果一样好,但它似乎看起来似乎有些合理超快速算法,用于枚举序列并将项目存储在内存缓冲区中,该缓冲区优于ToList可以执行的操作。

对于使用ToListToArray的小型序列不应产生任何可察觉的差异,如果您确实遇到性能问题,则应在决定如何解决之前对其进行测量。

答案 1 :(得分:1)

逻辑上,JArray是JSON结构中数组的表示。

逻辑上,JToken[]是一个JSON令牌数组。

就个人而言,我更愿意调用ToArray并拥有一个JTokens数组,因为我实际上并没有在这里构建一个JSON数组 - 我只是在内存中收集了一堆JTokens来处理它们。如果我想构建 - 或解构 - 一个真正的JSON结构,我只会使用JArray。它不是JToken[]的替代品。

答案 2 :(得分:-3)

Go for Array,因为它在内存中是固定大小的结构。