【问题标题】:c# List to LinkedList conversion [closed]c# List 到 LinkedList 的转换
【发布时间】:2020-12-14 19:51:24
【问题描述】:

我试图做一些谷歌工作,但找不到任何相关的答案。

我想从数据库中获取数据到链表。我发现的最简单的语法方法是使用 LINQ:

var linkedListData = myLinqToSqlQuery.ToList() as LinkedList<T>;

但是,我不确定这里内部发生​​了什么(我承认我懒得从 IL 那里找出答案)。

这种转换产生的内部结构是什么?它假装是链表,但是,我希望转换只会改变类型,而不是内部结构。因此,在内部,数据应该存储在数组而不是链表中。

任何人都可以在文档或博客文章中提供答案或指出一个很好的解释吗?


编辑

根据 cmets 和答案,我意识到我的问题有点过于复杂了。可以这么简单:

在 C# 中 List 和 LinkedList 之间的显式转换期间内部会发生什么?

它是否调用 LinkedList 构造函数?它是否调用了一些转换运算符(哪一个)?

List<T> list = new List<T>{ items };
var linkedList = list as LinkedList<T>;

【问题讨论】:

  • 无论如何,这编译失败CS0039 C# 无法通过引用转换、装箱转换、拆箱转换、包装转换或空类型转换将类型 System.Collections.Generic.List&lt;T&gt; 转换为 System.Collections.Generic.LinkedList&lt;T&gt;
  • IQueryable&lt;T&gt;.ToList() as LinkedList&lt;T&gt;,编译得很好。
  • @Vočko 你介意分享一个可以编译这行代码的最小代码示例吗?它不能为我编译,这里是对 SharpLab 的尝试:sharplab.io/…
  • 好吧,你必须得到一个 IQueryable 对象。我的示例有点过于复杂,无法在此处发布,但通常您需要dbContext.Items.Where(i =&gt; i.Id &gt; 0).Tolist() as LinkedList&lt;T&gt; 之类的内容,其中TItem 的一种类型
  • 出于好奇,new LinkedList(myLinqToSqlQuery) 有什么问题

标签: c# list .net-core linked-list type-conversion


【解决方案1】:

编辑:由于 OP 对问题和其他人提出的后续问题进行了编辑,因此我编辑了我的答案。

首先,List 到 LinkedList 没有任何隐式或显式转换。

但是,以下演示代码可以编译。虽然这与 OP 提出的问题并不完全相同,但我已经分解了这些步骤。

using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;

namespace linkedlist
{
    class Program
    {
        static void Main(string[] args)
        {
            var arr = new [] { "first", "second", "third" };
            var q1 = from x in arr
                     select x;
            var q = q1.ToList();
            var ll = new LinkedList<string>(q);

        }
    }
}

为什么不直接使用 List,除非您正在执行很多操作,LinkedList 与 List 相比是最佳的(参见 SO query and answers on List vs LinkedList)?

最后一条语句创建了一个新的LinkedList&lt;T&gt;,它复制了List&lt;T&gt; 的内容。

如果目的是从 LINQ 查询中获取 LinkedList,则以下内容会减少浪费:

    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        var arr = new [] { "first", "second", "third" };
        var q1 = from x in arr
                 select x;
        var ll = new LinkedList<string>(q1);

    }

实验

这里是一些关于性能的数据 LinqList&lt;T&gt;LinkedList&lt;T&gt;LinqLinkedList&lt;T&gt;

实验代码

using System;
using System.Linq;
using System.Collections.Generic;
using System.Data.Entity;

namespace linkedlist
{
    class Program
    {
        static void Main(string[] args)
        {
            var arr = new[] { "first", "second", "third" };
            var q1 = from x in arr
                     select x;

            for(var j = 0; j < 10; j++)
            {
                var st1 = DateTime.Now;
                for (var i = 0; i < 10000; i++)
                {
                    var q = q1.ToList();
                    var ll = new LinkedList<string>(q);
                }
                var en1 = DateTime.Now;
                Console.WriteLine($"With LINQ to List<T> to LinkedList<T> {(en1 - st1).TotalMilliseconds}");

                var st2 = DateTime.Now;
                for (var i = 0; i < 10000; i++)
                {
                    var ll = new LinkedList<string>(q1);
                }
                var en2 = DateTime.Now;
                Console.WriteLine($"With LinQ to LinkedList<T> {(en2 - st2).TotalMilliseconds}");
            }
        }
    }
}

计时结果:

截图:

应该忽略第一次运行以降低缓存预热效果,因为我们对两个测试使用相同的 LINQ 查询。对于每次试验 10,000 次迭代和总共 10 次试验,所有时间都是总经过的毫秒数。

With LINQ to List<T> to LinkedList<T> 20.0769
With LinQ to LinkedList<T> 8.6571

With LINQ to List<T> to LinkedList<T> 12.0162
With LinQ to LinkedList<T> 8.7212
With LINQ to List<T> to LinkedList<T> 12.7354
With LinQ to LinkedList<T> 8.3412
With LINQ to List<T> to LinkedList<T> 12.6848
With LinQ to LinkedList<T> 8.1306
With LINQ to List<T> to LinkedList<T> 12.3656
With LinQ to LinkedList<T> 8.5935
With LINQ to List<T> to LinkedList<T> 19.8802
With LinQ to LinkedList<T> 7.9596
With LINQ to List<T> to LinkedList<T> 12.1177
With LinQ to LinkedList<T> 9.0604
With LINQ to List<T> to LinkedList<T> 18.219
With LinQ to LinkedList<T> 11.115
With LINQ to List<T> to LinkedList<T> 18.4309
With LinQ to LinkedList<T> 11.2717
With LINQ to List<T> to LinkedList<T> 18.6743
With LinQ to LinkedList<T> 11.4202

结论:

Linq to LinkedList 比 Linq to List to LinkedList 更快,浪费更少。

【讨论】:

  • 我将使用 LinkedList 作为优先级队列,其中包含很多 AddFirst 和 AddAfter,因此 LinkedList 的性能应该会更好。您能否解释/获取有关转换更改内部结构的信息,因为这是我最初的问题。
  • @Vočko 如果您需要优先级队列,您应该考虑使用堆数据结构。 LinkedList 造成了一个糟糕的优先级队列。
  • 你错了@CoolBots。与查询到 List 到 LinkedList 的代码段相比,它的浪费更少。查询 List 会将列表具体化到内存中。 List 到 LinkedList 将被复制。对 LinkedList 的查询只会执行一次实现传递。
  • 你没有抓住重点。在包含 var q = q1.ToList(); 的代码块中将有一个额外的 List 完全在内存中。如果你有 100k 个项目,它会占用内存。在我回答的最后一个代码块中,我们没有这个 List 物化。我们有 var ll = new LinkedList(q1);它将直接在 LINQ 查询上执行 foreach 枚举。这就是为什么我说它不那么浪费。在前者中,在处理结束时内存中有两个副本,不包括 LINQ 内部内存。在后者中,只有一个副本,同样不包括 LINQ 内部内存。
  • foreach 确实枚举了。性能差异的原因是 q = q1.ToList() 进行了一次 foreach 枚举,而新的 LinkedList(q) 构造函数进行了另一个 foreach 枚举。而如果我们直接从 Linq 查询到 LinkedList() 构造函数,则只有一个 foreach 枚举。
猜你喜欢
  • 2012-06-25
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多