Перейти к содержанию

Коллекции

Раздел в разработке [15.02.2021]

При инициализации List не указывать 0 в качестве аргумента

Используя обычный конструктор без указания размера коллекции, памяти расходуем столько же, сколько и с указанием размера. Но работает почти в 2 раза медленнее.

img

Возвращать пустой массив как Array<T>.Empty()

Так быстрее и нет расхода памяти.

Пруф: https://www.tabsoverspaces.com/233833-best-way-to-create-an-empty-collection-array-and-list-in-csharp-net

Возвращать лучше IReadOnlyCollection, если результат потом не надо менять

У методов возвращаемое значение лучше делать IReadOnlyCollection<T>: мы можем вернуть как просто массив, так и List, если работали с ним и модифицировали его. При этом вызывающему коду будет пофиг, что ему возвращают - массив или List. Т.е. внутри методы мы можем выбрать более эффективный способ работы с коллекцией, при этом код, который нас использует, не зависит от внутренней реализации.

Linq

Linq To Objects

Использовать ToArray вместо ToList

Если нам надо вернуть список чего-либо, что меняться не будет, однозначно вызывать .ToArray() - он быстрее и меньше расходует памяти.

Пруф: https://stackoverflow.com/questions/1105990/is-it-better-to-call-tolist-or-toarray-in-linq-queries (коммент 06.02.2020)

Можно проверить самому. Надо взять Benchmark.NET, для него сделать вот такой тест:

[MemoryDiagnoser]
public class Benchmarks
{
    [Params(0, 1, 6, 10, 39, 100, 666, 1000, 1337, 10000)]
    public int Count { get; set; }

    public IEnumerable<int> Items => Enumerable.Range(0, Count);

    [Benchmark(Description = "ToArray()", Baseline = true)]
    public int[] ToArray() => Items.ToArray();

    [Benchmark(Description = "ToList()")]
    public List<int> ToList() => Items.ToList();

    public static void Main() => BenchmarkRunner.Run<Benchmarks>();
}

И запустить его. На выходе получаем вот такой результат.

BenchmarkDotNet=v0.12.1, OS=ubuntu 18.04
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=2.2.402
  [Host]     : .NET Core 2.2.8 (CoreCLR 4.6.28207.03, CoreFX 4.6.28208.02), X64 RyuJIT
  DefaultJob : .NET Core 2.2.8 (CoreCLR 4.6.28207.03, CoreFX 4.6.28208.02), X64 RyuJIT


|    Method | Count |         Mean |      Error |     StdDev | Ratio | RatioSD |  Gen 0 |  Gen 1 | Gen 2 | Allocated |
|---------- |------ |-------------:|-----------:|-----------:|------:|--------:|-------:|-------:|------:|----------:|
| ToArray() |     0 |     10.98 ns |   0.146 ns |   0.130 ns |  1.00 |    0.00 |      - |      - |     - |         - |
|  ToList() |     0 |     18.90 ns |   0.424 ns |   0.416 ns |  1.72 |    0.05 | 0.0063 |      - |     - |      40 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |     1 |     30.76 ns |   0.196 ns |   0.174 ns |  1.00 |    0.00 | 0.0114 |      - |     - |      72 B |
|  ToList() |     1 |     39.35 ns |   0.840 ns |   1.092 ns |  1.30 |    0.03 | 0.0178 |      - |     - |     112 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |     6 |     30.56 ns |   0.206 ns |   0.161 ns |  1.00 |    0.00 | 0.0139 |      - |     - |      88 B |
|  ToList() |     6 |     53.49 ns |   1.140 ns |   1.067 ns |  1.76 |    0.01 | 0.0203 |      - |     - |     128 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |    10 |     33.58 ns |   0.332 ns |   0.311 ns |  1.00 |    0.00 | 0.0165 |      - |     - |     104 B |
|  ToList() |    10 |     61.78 ns |   0.266 ns |   0.236 ns |  1.84 |    0.02 | 0.0228 |      - |     - |     144 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |    39 |     47.91 ns |   0.263 ns |   0.246 ns |  1.00 |    0.00 | 0.0356 |      - |     - |     224 B |
|  ToList() |    39 |    140.11 ns |   0.792 ns |   0.702 ns |  2.92 |    0.02 | 0.0417 |      - |     - |     264 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |   100 |     87.43 ns |   1.734 ns |   2.595 ns |  1.00 |    0.00 | 0.0737 |      - |     - |     464 B |
|  ToList() |   100 |    295.99 ns |   1.258 ns |   1.051 ns |  3.32 |    0.11 | 0.0796 |      - |     - |     504 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |   666 |    387.82 ns |   7.407 ns |   6.928 ns |  1.00 |    0.00 | 0.4334 | 0.0038 |     - |    2728 B |
|  ToList() |   666 |  1,734.96 ns |   9.221 ns |   7.700 ns |  4.48 |    0.09 | 0.4387 | 0.0076 |     - |    2768 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |  1000 |    567.14 ns |  11.399 ns |  19.965 ns |  1.00 |    0.00 | 0.6447 | 0.0086 |     - |    4064 B |
|  ToList() |  1000 |  2,557.64 ns |   7.868 ns |   7.360 ns |  4.50 |    0.15 | 0.6485 | 0.0114 |     - |    4104 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() |  1337 |    704.17 ns |   2.282 ns |   2.023 ns |  1.00 |    0.00 | 0.8602 | 0.0153 |     - |    5416 B |
|  ToList() |  1337 |  3,235.33 ns |  13.840 ns |  11.557 ns |  4.60 |    0.02 | 0.8659 | 0.0267 |     - |    5456 B |
|           |       |              |            |            |       |         |        |        |       |           |
| ToArray() | 10000 |  5,147.09 ns |  89.145 ns |  79.024 ns |  1.00 |    0.00 | 6.3629 | 0.7019 |     - |   40064 B |
|  ToList() | 10000 | 25,086.43 ns | 353.314 ns | 330.490 ns |  4.87 |    0.10 | 6.3477 | 1.2512 |     - |   40104 B |