Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将列表复制到新列表-更高效&;最佳做法_C# - Fatal编程技术网

C# 将列表复制到新列表-更高效&;最佳做法

C# 将列表复制到新列表-更高效&;最佳做法,c#,C#,将列表复制到新列表的适当方式是什么? 将列表复制到新列表的最有效方法是什么 通过高效,而不是代码效率,更多的是在幕后框架的意义上 List<String>List2 = List.ToList(); list2=List.ToList(); 或: List<String>List2 = new List<String>(); foreach (string item in List) { List2.Add(item); } list2=新列表();

将列表复制到新列表的适当方式是什么? 将列表复制到新列表的最有效方法是什么

通过高效,而不是代码效率,更多的是在幕后框架的意义上

List<String>List2 = List.ToList();
list2=List.ToList();
或:

List<String>List2 = new List<String>();
foreach (string item in List)
{
 List2.Add(item);
}
list2=新列表();
foreach(列表中的字符串项)
{
清单2.添加(项目);
}
更新:

List<String>List2 = new List<String>();
foreach (string item in List)
{
 List2.Add(item);
}

那么更高效的IL代码呢?

我相信这两个示例是相同的,而.ToList()实现的可能是后者

最好的性能如下所示:

List<String> list2 = new List<String>(list.Count);
foreach(String item in list)
    list2.Add(item);
List list2=新列表(List.Count);
foreach(列表中的字符串项)
清单2.添加(项目);
重要的部分是创建具有足够容量的list2来保存其内容

如果以后不需要修改任何一个列表,则只需要一个参考副本:

List<String> list2 = list;
List list2=列表;
鉴于
列表
有一个
IEnumerable
构造函数,我更喜欢这种形式:

List<string> newList = new List<string>(otherList);
List newList=新列表(otherList);
编辑

正如Ondrej在下面的反编译代码中指出的那样,
List
的构造函数预先分配数组的大小,并将内容复制到上面。这将比创建一个新列表,然后在其他列表上逐个添加项目要快得多,特别是在第二个示例中,您没有指定要预分配的项目数量。

您可以使用它来获取
IEnumerable

List list1=新列表();
//填写清单1
列表2=新列表(列表1);

就效率而言,第一种会更快
List
的底层实现是一个ArrayList,因此在调用
.Add
时,可能需要调整底层数组的大小

另一方面,
.ToList
可以确定新的
列表的正确初始大小
,并避免
foreach
技术遭受的重新分配操作

考虑到这一点,我推荐
.ToList
。代码越少,速度就越快

下面是一个简单的程序,您可以运行它来验证
ToList
是否确实更快:

void Main()
{
    List<int> items = new List<int>();

    items = Enumerable.Range(0, 1000000).ToList();

    CopyWithToList(items);
    CopyWithForeach(items);

}

public void CopyWithToList<T>(List<T> list) 
{
    var sw = Stopwatch.StartNew();
    List<T> copy = list.ToList();
    sw.Stop();
    Console.WriteLine("CopyWithToList: {0}", sw.Elapsed);
}

public void CopyWithForeach<T>(List<T> list)
{
    var sw = Stopwatch.StartNew();
    List<T> copy = new List<T>();
    foreach (T item in list) {
        copy.Add(item);
    }
    sw.Stop();

    Console.WriteLine("CopyWithForeach: {0}", sw.Elapsed);
}
void Main()
{
列表项=新列表();
items=可枚举的.Range(0,1000000).ToList();
复印件清单(项目);
CopyWithForeach(项目);
}
公共无效副本列表(列表)
{
var sw=Stopwatch.StartNew();
List copy=List.ToList();
sw.Stop();
WriteLine(“CopyWithToList:{0}”,sw.appeased);
}
公共作废CopyWithForeach(列表)
{
var sw=Stopwatch.StartNew();
列表副本=新列表();
foreach(列表中的T项){
副本。添加(项目);
}
sw.Stop();
WriteLine(“CopyWithForeach:{0}”,sw.appeased);
}
ToList的功能(简称):

公共静态列表列表(此IEnumerable源代码)
{
返回新列表(源);
}
ctor做什么(缩短):

公共列表(IEnumerable集合)
{
ICollection collection2=作为ICollection的集合;
int count=collection2.count;
此._items=新的T[计数];
collection2.CopyTo(此._项,0);
这个。_size=count;
}

因此ToList()的效率要高得多——它确实是先分配空间,然后一步复制所有项目。

测试表明,最好的性能是
.ToList()
方法(对于包含21474836个元素的列表,它在笔记本核心i5 CPU上运行约48毫秒)

其他方法的速度都比较慢,而使用
.Add()
的方法的性能最差

下面是一些测试代码:

class Program
{
    static void Main()
    {
        var list = new List<int>();

        for (int i = 0; i < int.MaxValue / 100; i++)
        {
            list.Add(i);
        }

        TimeItAccurate(ListCopy_1, list, 10);
        TimeItAccurate(ListCopy_2, list, 10);
        TimeItAccurate(ListCopy_3, list, 10);
        TimeItAccurate(ListCopy_4, list, 10);
        TimeItAccurate(ListCopy_5, list, 10);
    }

    private static List<int> ListCopy_1(List<int> list)
    {
        var newList = list.ToList();

        return newList;
    }

    private static List<int> ListCopy_2(List<int> list)
    {
        var newList = new List<int>(list.Count);

        foreach (var i in list)
        {
            newList.Add(i);
        }

        return newList;
    }

    private static List<int> ListCopy_3(List<int> list)
    {
        var newList = new List<int>(list.ToArray());

        return newList;
    }

    private static List<int> ListCopy_4(List<int> list)
    {
        var newList = new List<int>(list.Count);

        newList.AddRange(list);

        return newList;
    }

    private static List<int> ListCopy_5(List<int> list)
    {
        var newList = new List<int>(list);

        return newList;
    }

    public static void TimeItAccurate<TIn, TResult>(Func<TIn, TResult> func, TIn argument, int iterationsCount)
    {
        #region Pre-heat
        for (int i = 0; i < 10; i++)
        {
            var t = func.Invoke(argument);
        }
        #endregion

        var stopwatch = new Stopwatch();
        var result = default(TResult);

        stopwatch.Start();
        for (int i = 0; i < iterationsCount; i++)
        {
            result = func.Invoke(argument);
        }
        stopwatch.Stop();

        Console.WriteLine("Result:\n{4}(...) == {0}\n\n{1} iterations done in {2} ms.\nAverage time: {3:f5} ms.",
            result,
            iterationsCount,
            stopwatch.ElapsedMilliseconds,
            stopwatch.ElapsedMilliseconds / (double)iterationsCount,
            func.Method.Name);
    }
}
类程序
{
静态void Main()
{
var list=新列表();
对于(int i=0;i
结果是:

Result (.ToList()):
ListCopy_1(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 474 ms.
Average time: 47.40000 ms.

Result (for-cycle with .Add()):
ListCopy_2(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 1896 ms.
Average time: 189.60000 ms.

Result (ctor with .ToArray()):
ListCopy_3(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 981 ms.
Average time: 98.10000 ms.

Result (.AddRange()):
ListCopy_4(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 959 ms.
Average time: 95.90000 ms.

Result (new List<int>(list)):
ListCopy_5(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 480 ms.
Average time: 48.00000 ms.
Result(.ToList()):
ListCopy_1(…)==System.Collections.Generic.List`1[System.Int32]
在474毫秒内完成10次迭代。
平均时间:47.40000毫秒。
结果(对于带有.Add()的循环):
ListCopy_2(…)==System.Collections.Generic.List`1[System.Int32]
10次迭代
class Program
{
    static void Main()
    {
        var list = new List<int>();

        for (int i = 0; i < int.MaxValue / 100; i++)
        {
            list.Add(i);
        }

        TimeItAccurate(ListCopy_1, list, 10);
        TimeItAccurate(ListCopy_2, list, 10);
        TimeItAccurate(ListCopy_3, list, 10);
        TimeItAccurate(ListCopy_4, list, 10);
        TimeItAccurate(ListCopy_5, list, 10);
    }

    private static List<int> ListCopy_1(List<int> list)
    {
        var newList = list.ToList();

        return newList;
    }

    private static List<int> ListCopy_2(List<int> list)
    {
        var newList = new List<int>(list.Count);

        foreach (var i in list)
        {
            newList.Add(i);
        }

        return newList;
    }

    private static List<int> ListCopy_3(List<int> list)
    {
        var newList = new List<int>(list.ToArray());

        return newList;
    }

    private static List<int> ListCopy_4(List<int> list)
    {
        var newList = new List<int>(list.Count);

        newList.AddRange(list);

        return newList;
    }

    private static List<int> ListCopy_5(List<int> list)
    {
        var newList = new List<int>(list);

        return newList;
    }

    public static void TimeItAccurate<TIn, TResult>(Func<TIn, TResult> func, TIn argument, int iterationsCount)
    {
        #region Pre-heat
        for (int i = 0; i < 10; i++)
        {
            var t = func.Invoke(argument);
        }
        #endregion

        var stopwatch = new Stopwatch();
        var result = default(TResult);

        stopwatch.Start();
        for (int i = 0; i < iterationsCount; i++)
        {
            result = func.Invoke(argument);
        }
        stopwatch.Stop();

        Console.WriteLine("Result:\n{4}(...) == {0}\n\n{1} iterations done in {2} ms.\nAverage time: {3:f5} ms.",
            result,
            iterationsCount,
            stopwatch.ElapsedMilliseconds,
            stopwatch.ElapsedMilliseconds / (double)iterationsCount,
            func.Method.Name);
    }
}
Result (.ToList()):
ListCopy_1(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 474 ms.
Average time: 47.40000 ms.

Result (for-cycle with .Add()):
ListCopy_2(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 1896 ms.
Average time: 189.60000 ms.

Result (ctor with .ToArray()):
ListCopy_3(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 981 ms.
Average time: 98.10000 ms.

Result (.AddRange()):
ListCopy_4(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 959 ms.
Average time: 95.90000 ms.

Result (new List<int>(list)):
ListCopy_5(...) == System.Collections.Generic.List`1[System.Int32]

10 iterations done in 480 ms.
Average time: 48.00000 ms.