Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

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 purposes the collection is immutable. I would think to just return an array, but some people have said to not return variable sized arrays from a function as it is "poor form". Not sure why?

Does it matter that this needs to be .NET 2.0 compliant?

like image 253
DevDevDev Avatar asked Aug 13 '09 22:08

DevDevDev


People also ask

Can you return arrays in C?

C programming does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.

Why can't you return an array in C?

C returns by value. Arrays cannot be passed by value, therefore they cannot be returned.

Why should properties not return arrays?

Arrays returned by properties are not write-protected, even if the property is read-only. To keep the array tamper-proof, the property must return a copy of the array. Typically, users won't understand the adverse performance implications of calling such a property.


4 Answers

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.

like image 143
Reed Copsey Avatar answered Oct 06 '22 07:10

Reed Copsey


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>.

like image 37
Sam Harwell Avatar answered Oct 06 '22 07:10

Sam Harwell


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
like image 35
JaredPar Avatar answered Oct 06 '22 09:10

JaredPar


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;
    }

}
like image 20
Roman Pokrovskij Avatar answered Oct 06 '22 09:10

Roman Pokrovskij