Is it bad form to return Arrays in C#? Should I return List?

后端 未结 7 1063
南方客
南方客 2020-12-14 20:31

I have a function which returns a variable number of elements, should I return an array or a List? The \"collection\'s\" size does not change once returned, ie for all purpo

相关标签:
7条回答
  • 2020-12-14 21:13

    One opinion I see pretty often a suggestion to return either IList<T> or ReadOnlyCollection<T>. It's OK to return these if you have one of these available - both can be assigned directly to an IEnumerable<T> (they work directly with any LINQ methods). One thing to note is ReadOnlyCollection<T> is a very lightweight type that can wrap any IList<T>.

    0 讨论(0)
  • 2020-12-14 21:14

    If the size of the collection is not to change after being returned IEnumerable<T> would be my choice, since the caller could then use LINQ extension methods with the list immediately.

    0 讨论(0)
  • 2020-12-14 21:21

    It's bad form to return arrays if not needed, and especially to return List<T>.

    Usually, you'll want to return IEnumerable<T> or IList<T>.

    If your user is going to just need to run through each element, IEnumerable<T> will provide this capability. It also allows you to potentially implement the routine (now or later) using deferred execution.

    If your user needs to access elements by index, return IList<T>. This provides all of the benefits of arrays, but gives you more flexibility in your implementation. You can implement it as an array, a list, or some other collection that implements IList<T>, and you don't have to convert/copy to an array.

    0 讨论(0)
  • 2020-12-14 21:28

    Return IEnumerable unless you need:

    1. access Count - then return IReadOnlyCollection.
    2. modify elements and Count is less the ArrayList.Capacity - then return array.
    3. add new elements - then return list.
    4. some microoptimizations - do benchmark. E.g. foreach over array is quicker then over the list

    BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 1 (10.0.14393) Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4 Frequency=3233538 Hz, Resolution=309.2588 ns, Timer=TSC [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0 Clr : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0 Core : .NET Core 4.6.25211.01, 64bit RyuJIT

        Method |  Job | Runtime |       Mean |      Error |    StdDev |        Min |        Max |     Median | Rank | Allocated |
    ---------- |----- |-------- |-----------:|-----------:|----------:|-----------:|-----------:|-----------:|-----:|----------:|
      TestList |  Clr |     Clr | 5,153.3 ns |  34.002 ns | 31.806 ns | 5,119.2 ns | 5,213.4 ns | 5,135.9 ns |    3 |       0 B |
     TestArray |  Clr |     Clr |   730.1 ns |   6.962 ns |  6.512 ns |   722.4 ns |   743.9 ns |   729.5 ns |    2 |       0 B |
      TestList | Core |    Core | 5,188.4 ns | 102.816 ns | 96.174 ns | 5,070.3 ns | 5,342.6 ns | 5,185.6 ns |    3 |       0 B |
     TestArray | Core |    Core |   709.0 ns |   6.126 ns |  5.730 ns |   700.8 ns |   718.6 ns |   708.1 ns |    1 |       0 B |
    

    Code:

    [RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
    [ClrJob, CoreJob]
    [HtmlExporter, MarkdownExporter]
    [MemoryDiagnoser]
    public class BenchmarkForEach
    {
        List<string> testData = new List<string>();
        string[] testArray;
        public BenchmarkForEach()
        {
            for(int i=0;i<1000;i++)
            {
                testData.Add(i.ToString());
            }
            testArray = testData.ToArray();
        }
        [Benchmark]
        public int TestList()
        {
            var x = 0;
            foreach(var i in testData)
            {
                x += i.Length;
            }
            return x;
        }
        [Benchmark]
        public int TestArray()
        {
            var x = 0;
            foreach (var i in testArray)
            {
                x += i.Length;
            }
            return x;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-14 21:31

    Expanding on Reed's answer.

    Eric Lippert did a great blog post on this very subject. It's got probably the most detailed answer available

    • http://blogs.msdn.com/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx
    0 讨论(0)
  • 2020-12-14 21:31

    It is easy to get an array from an IList if an array is what you need, but the reverse is not true. So returning an IList is preferable.

    0 讨论(0)
提交回复
热议问题