By Frederick The Fool


2009-01-12 08:08:33 8 Comments

MyClass[] array;
List<MyClass> list;

What are the scenarios when one is preferable over the other? And why?

15 comments

@snipsnipsnip 2018-02-27 06:06:04

Since no one mention: In C#, an array is a list. MyClass[] and List<MyClass> both implement IList<MyClass>. (e.g. void Foo(IList<int> foo) can be called like Foo(new[] { 1, 2, 3 }) or Foo(new List<int> { 1, 2, 3 }) )

So, if you are writing a method that accepts a List<MyClass> as an argument, but uses only subset of features, you may want to declare as IList<MyClass> instead for callers' convenience.

Details:

@Melbourne Developer 2019-01-07 23:50:56

Arrays Vs. Lists is a classic maintainability vs. performance problem. The rule of thumb that nearly all developers follow is that you should shoot for both, but when they come in to conflict, choose maintainability over performance. The exception to that rule is when performance has already proven to be an issue. If you carry this principle in to Arrays Vs. Lists, then what you get is this:

Use strongly typed lists until you hit performance problems. If you hit a performance problem, make a decision as to whether dropping out to arrays will benefit your solution with performance more than it will be a detriment to your solution in terms of maintenance.

@Bimal Poudel 2018-12-15 21:07:52

Populating a list is easier than an array. For arrays, you need to know the exact length of data, but for lists, data size can be any. And, you can convert a list into an array.

List<URLDTO> urls = new List<URLDTO>();

urls.Add(new URLDTO() {
    key = "wiki",
    url = "https://...",
});

urls.Add(new URLDTO()
{
    key = "url",
    url = "http://...",
});

urls.Add(new URLDTO()
{
    key = "dir",
    url = "https://...",
});

// convert a list into an array: URLDTO[]
return urls.ToArray();

@user3290232 2018-04-15 22:16:01

They may be unpopular, but I am a fan of Arrays in game projects. - Iteration speed can be important in some cases, foreach on an Array has significantly less overhead if you are not doing much per element - Adding and removing is not that hard with helper functions - Its slower, but in cases where you only build it once it may not matter - In most cases, less extra memory is wasted (only really significant with Arrays of structs) - Slightly less garbage and pointers and pointer chasing

That being said, I use List far more often than Arrays in practice, but they each have their place.

It would be nice if List where a built in type so that they could optimize out the wrapper and enumeration overhead.

@iliketocode 2017-07-09 05:39:41

Lists in .NET are wrappers over arrays, and use an array internally. The time complexity of operations on lists is the same as would be with arrays, however there is a little more overhead with all the added functionality / ease of use of lists (such as automatic resizing and the methods that come with the list class). Pretty much, I would recommend using lists in all cases unless there is a compelling reason not to do so, such as if you need to write extremely optimized code, or are working with other code that is built around arrays.

@Marc Gravell 2009-01-12 08:10:58

It is rare, in reality, that you would want to use an array. Definitely use a List<T> any time you want to add/remove data, since resizing arrays is expensive. If you know the data is fixed length, and you want to micro-optimise for some very specific reason (after benchmarking), then an array may be useful.

List<T> offers a lot more functionality than an array (although LINQ evens it up a bit), and is almost always the right choice. Except for params arguments, of course. ;-p

As a counter - List<T> is one-dimensional; where-as you have have rectangular (etc) arrays like int[,] or string[,,] - but there are other ways of modelling such data (if you need) in an object model.

See also:

That said, I make a lot of use of arrays in my protobuf-net project; entirely for performance:

  • it does a lot of bit-shifting, so a byte[] is pretty much essential for encoding;
  • I use a local rolling byte[] buffer which I fill before sending down to the underlying stream (and v.v.); quicker than BufferedStream etc;
  • it internally uses an array-based model of objects (Foo[] rather than List<Foo>), since the size is fixed once built, and needs to be very fast.

But this is definitely an exception; for general line-of-business processing, a List<T> wins every time.

@Frederick The Fool 2009-01-12 08:25:54

The argument about resizing is totally valid. However people prefer Lists even when no resizing is needed. For this latter case, is there a solid, logical argument or is it nothing more than "arrays are out of fashion"?

@Marc Gravell 2009-01-12 08:28:24

@Frederick: hard to answer without hearing the "why". Actually, in many cases I'd prefer IList<T> or IEnumerable<T> - it lets the caller decide what they want to use (T[] or List<T> etc). LINQ largely balances out a lot of the extra List<T> functions (over IList<T>).

@Frederick The Fool 2009-01-12 08:37:13

Actually, I'm working with a legacy, C# 1.0 codebase. Some of the functions there take and return arrays. No resizing or anything is happening....

@Frederick The Fool 2009-01-12 08:38:01

...Now, in my wrapper functions, I'm inclined to use List<T>'s instead of arrays. But I have no solid reasoning to justify this. Just a warm fuzzy feeling. I need a good argument for my decision.

@Marc Gravell 2009-01-12 08:40:30

Well, things are slightly different without generics... Boxing and casting aren't the worst things in the world, but it adds up. I'd say that arrays have a bit more place in .NET 1.x than now, but there is still ArrayList etc if you can live with the box/cast/no-compile-time-checking pain.

@Marc Gravell 2009-01-12 08:41:27

@Frederick - seriously: consider IList<T> (if you need add/remove/indexer) or IEnumerable<T> (if you just need foreach).

@Frederick The Fool 2009-01-12 08:49:00

I don't fully understand this: does working with an array need boxing/unboxing? Even if the type contained in the array is a ref type? And is casting needed too? But isn't an array strongly typed? PS: I'm just curious if there's just some dogma against arrays. PPS: Yet to read Jon Skeet's link.

@Frederick The Fool 2009-01-12 08:51:28

Yeah. I appreciate and agree with using IList<T> and IEnumerable<T>. They make your class user less constrained in terms of what to supply to and expect back from your class.

@Marc Gravell 2009-01-12 08:55:17

@Frederick - my boxing/cast comments were directed at ArrayList etc, since they are the closest option to List<T> in .NET 1.x

@dan-gph 2010-03-09 06:49:26

"Definitely use a List<T> any time you want to add/remove data, since resizing arrays is expensive." List<T> uses an array internally. Were you thinking of LinkedList<T>?

@Lucas Werkmeister 2013-10-17 15:04:45

@Dangph: A List<T> keeps the array bigger than it needs to be, so not every add/remove operation needs to resize the array, since there's still free space at the end of the array most of the time.

@dan-gph 2013-10-18 03:17:52

@lucas, but what if you remove an item from the middle of the array? All the elements above it will have to be shuffled along to fill up the hole.

@Gaui 2013-11-04 11:48:20

Except for params arguments, of course ;-p Why except for params arguments? Could you explain a bit?

@Marc Gravell 2013-11-04 11:53:34

@Gaui because params only exists for vectors; so this is one of the places where it is more natural to use a naked array. Of course, personally I'm very anti-invisible-allocation, so I try to avoid params in the first place.

@heltonbiker 2014-06-11 19:51:57

You wrote "there are other ways of modelling such [n-dimensional] data (if you need) in an object model." Well I do need, since the application I work makes heavy use of n-dimensional data, and I am happily using double[,], Point3D[,], and the like. Do you have any resource to point regarding appropriate object models for that use, which are better than plain arrays? My arrays are usually dense and do not resize or reshape. Thanks!

@Eamon Nerbonne 2014-06-20 09:35:09

More features == more complex == not good, unless you need those features. This answer basically lists reasons why array's are better, yet draws the opposite conclusion.

@Casey 2014-07-17 21:17:10

@lucas.werkmeister Yes. There's nothing stopping you from doubling the array size when it fills yourself either so the expense of resizing an array is irrelevant.

@Casey 2014-07-17 21:19:33

@EamonNerbonne I don't really agree with that. Most of the "features" you're talking about (like implementing dynamic arrays) are not like, newfangled junk you're hardly ever going to use.

@Eamon Nerbonne 2014-07-18 11:48:00

@emodendroket It doesn't matter whether they're newfangled, it's extra complexity you just don't need. Are you actually using those features? No? Don't use a List<>. Since datastructures that change over time make code difficult to reason about, I'd actively recommend you don't use List<>.Add unless you've given it careful consideration; array's simply remove one more source of bugs in code that doesn't need dynamic resizing (i.e. most code).

@Marc Gravell 2014-07-18 11:52:37

@EamonNerbonne if you're not using those features, I can pretty much guarantee that they aren't going to hurt you... but: the number of collections that never need mutation is much smaller, in my experience, than those that are mutated

@Eamon Nerbonne 2014-07-18 12:38:14

@MarcGravell: that depends on your coding style. In my experience virtually no collections are ever mutated. That is; collections are retrieved from the database or constructed from some source, but further processing is always done by recreating a new collection (e.g. map/filter etc). Even where conceptual mutation is necessary, it tends to be simplest to just generate a new collection. I only ever mutate a collection as a performance optimization, and such optimizations tend to be highly local and not expose the mutation to API consumers.

@Eamon Nerbonne 2014-07-18 12:47:47

@MarcGravell: For some context, non-mutating collections is clearly what LINQ is best at, and that's not an uncommon API nowadays. It's both odd to "mutate" the result of a linq query (why didn't you select+project correctly in the first place?), and it's conceptually tricky to mutate the source of a linq query due to the mixture of eager and lazy evaluation. If you're building a database-backed website, I'd be curious if there's any (common) use case at all for mutable collections - outside the database itself, of course.

@Casey 2014-07-18 13:48:51

@EamonNerbonne I couldn't disagree more that "most code" does not need array resizing and there are lots of other things you have to worry about going wrong if you're working with arrays.

@Eamon Nerbonne 2014-07-18 14:52:56

@emodendroket: Some code deals with collections by manually looping, processing datastructures as it goes. This code likes foreach and List<>.Add. Other code deals with collections as values, and computes new collections from old. Such code likes LINQ, and has little use for mutable collections. This answer implicitly prefers loops+mutation over functional constructs, and I don't think such a preference should be implicitly stated as fact the way it is. Most code I see tends towards the functional - computing new collections (or iterators) from existing, unchanged data.

@Eamon Nerbonne 2014-07-18 14:57:56

@MarcGravell: List<> mutability hurts in practice precisely because some code conventionally expects changes to performed by mutation. Avoiding the Add method immediately avoids the #1 source of accidental misuse, and from experience in a large project, I can say that such bugs are nasty because (just like null-deref bugs) the code that crashes or computes the wrong value is often far removed from the source of the error (the code that changed an internal datastructure that was presumed to be unchanging). TL;DR: If you're going the LINQ route, what's the use-case for List<>?

@Casey 2014-07-18 16:51:23

@EamonNerbonne If you want immutable collections, you should actually use an immutable collection. Arrays are mutable; they're just fixed in length.

@Casey 2014-07-18 16:52:44

@EamonNerbonne Arrays are the best choice in the rather infrequent circumstance that you need a mutable collection, but one that is fixed in length. That isn't functional programming at all.

@Eamon Nerbonne 2014-07-21 12:39:34

@emodendroket: Arrays aren't perfect, but they're better than List<> if you don't need mutability: they're faster, use less memory, and avoid the most common mutable operation. Unfortunately, .NET does not provide a comparable immutable array (there's a nuget package for System.Collections.Immutable, but the array implementation is still prerelease only), and even once it does, not everyone can update to the latest .NET immediately and the immutability wrapper will have some overhead. All in all: right now, Array is good enough (and certainly better than List<> non-mutating use-cases.

@Eamon Nerbonne 2014-07-21 12:40:59

@emodendroket: think of it this way: precisely because List<> is so appropriate for mutating collections, it's inappropriate for non-mutating collections because the type conveys the wrong message.

@Casey 2014-07-21 20:49:13

@EamonNerbonne Well, using ReadOnlyCollection<T> would send that message even more strongly.

@Eamon Nerbonne 2014-07-22 07:08:52

@emodendroket: ReadOnlyCollection<T> a lot more verbose, and horrifically slow. For a public API - sure. But most code isn't in the public API, and coding conventions that state "don't mess with array contents after construction" work fine. Enforces immutability isn't natural or easy in C#, and I don't think the additional mental and runtime overhead is worth it, especially when simple conventions are almost just as good, and much simpler and faster.

@barlop 2016-09-23 05:02:02

why do you say "List<T> is one-dimensional; where-as you have have rectangular (etc) arrays" <--- Indeed you can have recangular or jagged arrays, but similarly, you can have List<List<string>> So why suggest that List is 1D when it's not anymore or less 1D than arrays?

@Marc Gravell 2016-09-23 06:53:16

@barlop k; int[,] is explicitly a 2D array. int[,,] is explicitly a 3d array. int[][] however is not a "2d array" - it is a 1D array of 1D arrays, aka a jagged array. Likewise List<List<int>> is not a 2D list: it is a list of lists. The point is that in the case of int[,] there is one array, so we can describe the properties of that 1 array. In the case of List<List<int>> there are n+1 lists; one is a 1D list of lists, when are 1D lists of ints. Yes, you can use a List<List<int>> to express 2D data, but that isn't the same thing. Semantics matter.

@tfrascaroli 2017-08-29 12:11:56

@MarcGravell What about switching between Lists and Arrays when the case requires. i.e, once the list is size-fixed, switch to array and perform stuff on the array, and maybe if we need to extensively add/remove again switch back again to lists (using LINQ)

@Marc Gravell 2017-08-29 20:11:30

@tfrascaroli you can't simply switch between arrays and lists without paying allocation+copy costs which would make any such approach prohibitively expensive

@tfrascaroli 2017-08-29 20:39:16

@MarcGravell yeah, I figured that. The thing is, if list is cheaper to add/remove elements, and then an array is cheaper to read and use, maybe a conversion right after we're done adding wouldn' be that bad. But I agree that the approach looks to be a complete waste of resources. I don't know how the conversions in LINQ are implemented internally though...

@solstice333 2019-01-31 11:59:22

Arrays for variadic params or to guarantee fixed size. List to deal with resize.

@solstice333 2019-01-31 12:14:12

Also, some API's just naturally return Array like for example Regex.split

@moarboilerplate 2015-04-28 21:22:49

Rather than going through a comparison of the features of each data type, I think the most pragmatic answer is "the differences probably aren't that important for what you need to accomplish, especially since they both implement IEnumerable, so follow popular convention and use a List until you have a reason not to, at which point you probably will have your reason for using an array over a List."

Most of the time in managed code you're going to want to favor collections being as easy to work with as possible over worrying about micro-optimizations.

@Herman Schoenfeld 2015-03-05 01:37:08

Arrays should be used in preference to List when the immutability of the collection itself is part of the contract between the client & provider code (not necessarily immutability of the items within the collection) AND when IEnumerable is not suitable.

For example,

var str = "This is a string";
var strChars = str.ToCharArray();  // returns array

It is clear that modification of "strChars" will not mutate the original "str" object, irrespective implementation-level knowledge of "str"'s underlying type.

But suppose that

var str = "This is a string";
var strChars = str.ToCharList();  // returns List<char>
strChars.Insert(0, 'X');

In this case, it's not clear from that code-snippet alone if the insert method will or will not mutate the original "str" object. It requires implementation level knowledge of String to make that determination, which breaks Design by Contract approach. In the case of String, it's not a big deal, but it can be a big deal in almost every other case. Setting the List to read-only does help but results in run-time errors, not compile-time.

@supercat 2014-08-21 21:17:28

Another situation not yet mentioned is when one will have a large number of items, each of which consists of a fixed bunch of related-but-independent variables stuck together (e.g. the coordinates of a point, or the vertices of a 3d triangle). An array of exposed-field structures will allow the its elements to be efficiently modified "in place"--something which is not possible with any other collection type. Because an array of structures holds its elements consecutively in RAM, sequential accesses to array elements can be very fast. In situations where code will need to make many sequential passes through an array, an array of structures may outperform an array or other collection of class object references by a factor of 2:1; further, the ability to update elements in place may allow an array of structures to outperform any other kind of collection of structures.

Although arrays are not resizable, it is not difficult to have code store an array reference along with the number of elements that are in use, and replace the array with a larger one as required. Alternatively, one could easily write code for a type which behaved much like a List<T> but exposed its backing store, thus allowing one to say either MyPoints.Add(nextPoint); or MyPoints.Items[23].X += 5;. Note that the latter would not necessarily throw an exception if code tried to access beyond the end of the list, but usage would otherwise be conceptually quite similar to List<T>.

@Carl 2017-09-15 07:58:43

What you described is a List<>. There's an indexer so you can access the underlying array directly, and the List<> will maintain the size for you.

@supercat 2017-09-15 15:09:54

@Carl: Given e.g. Point[] arr;, it's possible for code to say, e.g. arr[3].x+=q;. Using e.g. List<Point> list, it would be necessary to instead say Point temp=list[3]; temp.x+=q; list[3]=temp;. It would be helpful if List<T> had a method Update<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params). and compilers could turn list[3].x+=q; into {list.Update(3, (ref int value, ref int param)=>value+=param, ref q); but no such feature exists.

@Carl 2017-09-17 01:53:37

Good news. It works. list[0].X += 3; will add 3 to the X property of the first element of the list. And list is a List<Point> and Point is a class with X and Y properties

@Sune Rievers 2009-11-23 09:45:58

Most of the times, using a List would suffice. A List uses an internal array to handle its data, and automatically resizes the array when adding more elements to the List than its current capacity, which makes it more easy to use than an array, where you need to know the capacity beforehand.

See http://msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx#datastructures20_1_topic5 for more information about Lists in C# or just decompile System.Collections.Generic.List<T>.

If you need multidimensional data (for example using a matrix or in graphics programming), you would probably go with an array instead.

As always, if memory or performance is an issue, measure it! Otherwise you could be making false assumptions about the code.

@dragonfly 2012-08-07 06:54:58

Hi, could you explain why "A list's lookup time would be O(n)" is true? As far as I know List<T> uses array behind the scenes.

@Sune Rievers 2012-08-07 08:30:16

@dragonfly you're totally right. Source. At the time, I assumed that the implementation used pointers, but I've since learned otherwise. From the link above: 'Retrieving the value of this property is an O(1) operation; setting the property is also an O(1) operation.'

@dragonfly 2012-08-07 08:31:28

Great, thanks for answer.

@smack0007 2009-01-12 08:37:01

If I know exactly how many elements I'm going to need, say I need 5 elements and only ever 5 elements then I use an array. Otherwise I just use a List<T>.

@Oliver 2017-04-25 11:39:03

Why wouldn't you use a List<T> in the case where you know the number of elements?

@Jon Skeet 2009-01-12 08:26:44

Really just answering to add a link which I'm surprised hasn't been mentioned yet: Eric's Lippert's blog entry on "Arrays considered somewhat harmful."

You can judge from the title that it's suggesting using collections wherever practical - but as Marc rightly points out, there are plenty of places where an array really is the only practical solution.

@Spencer Ruport 2012-04-20 19:36:14

Finally got around to reading this over 3 years later haha. Good article then, good article now. :)

@stt106 2015-04-07 22:06:08

Personally that blog link is the answer...

@Alnitak 2009-01-12 08:16:48

Notwithstanding the other answers recommending List<T>, you'll want to use arrays when handling:

  • image bitmap data
  • other low-level data-structures (i.e. network protocols)

@Konrad Rudolph 2009-01-12 08:28:31

Why for network protocols? Wouldn't you rather use custom structures here and give them an special serializer or an explicit memory layout? Furthermore, what speaks against using a List<T> here rather than a byte array?

@Marc Gravell 2009-01-12 08:37:05

@Konrad - well, for starters, Stream.Read and Stream.Write work with byte[], as does Encoding etc...

@sajidnizami 2009-01-12 08:16:28

It completely depends on the contexts in which the data structure is needed. For example, if you are creating items to be used by other functions or services using List is the perfect way to accomplish it.

Now if you have a list of items and you just want to display them, say on a web page array is the container you need to use.

@Marc Gravell 2009-01-12 08:18:46

If you have a list of items and you just want to display them, then what is wrong with just using the list you already have? What would an array offer here?

@Marc Gravell 2009-01-12 08:47:00

And for "creating items to be used by other functions or services", actually, I'd prefer an iterator block with IEnumerable<T> - then I can stream objects rather than buffer them.

@Spencer Ruport 2009-01-12 08:12:54

Unless you are really concerned with performance, and by that I mean, "Why are you using .Net instead of C++?" you should stick with List<>. It's easier to maintain and does all the dirty work of resizing an array behind the scenes for you. (If necessary, List<> is pretty smart about choosing array sizes so it doesn't need to usually.)

@Bengt 2011-06-12 04:54:06

"Why are you using .Net instead of C++?" XNA

Related Questions

Sponsored Content

33 Answered Questions

[SOLVED] For-each over an array in JavaScript?

84 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5966857 View
  • 7434 Score
  • 84 Answer
  • Tags:   javascript arrays

15 Answered Questions

[SOLVED] How to clone or copy a list?

34 Answered Questions

[SOLVED] Create ArrayList from array

44 Answered Questions

[SOLVED] How to make a flat list out of list of lists

46 Answered Questions

[SOLVED] How to check if an object is an array?

26 Answered Questions

[SOLVED] Why not inherit from List<T>?

28 Answered Questions

[SOLVED] How do I check if a list is empty?

  • 2008-09-10 06:20:11
  • Ray Vega
  • 2416228 View
  • 3235 Score
  • 28 Answer
  • Tags:   python list

60 Answered Questions

[SOLVED] How do you split a list into evenly sized chunks?

16 Answered Questions

Sponsored Content