C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
With it, we do not need to manage the size on our own. This type is ideal for linear collections not accessed by keys.
Dynamic in size, with many methods, List makes life easier. List is a generic type. We need to use < and > in the List declaration. It is a newer, faster ArrayList.
First, we declare a List of int values. We create a new List of unspecified size and adds four prime numbers to it. Values are stored in the order added.
Note: There are other ways to create, and add elements to, Lists—this is not the simplest.
Tip: The angle brackets are part of the declaration type. They are not conditional (less or more than) operators.
Based on: .NET 4.5 C# program that adds elements to List using System.Collections.Generic; class Program { static void Main() { List<int> list = new List<int>(); list.Add(2); list.Add(3); list.Add(5); list.Add(7); } }
A note. The above example adds a primitive type (int) to a List collection. But a List can also hold reference types and object instances. Non-int types work just as well.
AddRange. For adding many elements at once—adding an array to a List—we use the AddRange method. This can simplify code that combines collections.
Loops. We loop through a List with the for and foreach-loops. The syntax is like that for an array, except we use Count, not Length, for the upper bound.
Tip: We can loop backwards through a List. Start with list.Count - 1, and decrement to >= 0.
C# program that loops through List using System; using System.Collections.Generic; class Program { static void Main() { List<int> list = new List<int>(); list.Add(2); list.Add(3); list.Add(7); foreach (int prime in list) // Loop through List with foreach. { Console.WriteLine(prime); } for (int i = 0; i < list.Count; i++) // Loop with for. { Console.WriteLine(list[i]); } } } Output: repeated twice 2 3 7
Count, clear. To get the number of elements, access the Count property. This is fast—just avoid the Count extension method. Count, on the List type, is equal to Length on arrays.
Clear: Here we use the Clear method, along with the Count property, to erase all the elements in a List.
Info: Before Clear is called, this List has 3 elements. After Clear is called, it has 0 elements.
Null: We can assign the List to null instead of calling Clear, with similar performance.
C# program that counts List using System; using System.Collections.Generic; class Program { static void Main() { List<bool> list = new List<bool>(); list.Add(true); list.Add(false); list.Add(true); Console.WriteLine(list.Count); // 3 list.Clear(); Console.WriteLine(list.Count); // 0 } } Output 3 0
Copy array. Here we create a List with elements from an array. We use the List constructor and pass it the array. List receives this parameter and fills its values from it.
Caution: The array element type must match the List element type or compilation will fail.
C# program that copies array to List using System; using System.Collections.Generic; class Program { static void Main() { int[] arr = new int[3]; // New array with 3 elements. arr[0] = 2; arr[1] = 3; arr[2] = 5; List<int> list = new List<int>(arr); // Copy to List. Console.WriteLine(list.Count); // 3 elements in List. } } Output 3
Test elements. We test each element for a certain value. This example shows a foreach-loop, which tests to see if 3 is in a list of primes.
C# program that uses foreach using System; using System.Collections.Generic; class Program { static void Main() { // New list for example. List<int> primes = new List<int>(new int[] { 2, 3, 5 }); // See if List contains 3. foreach (int number in primes) { if (number == 3) // Will match once. { Console.WriteLine("Contains 3"); } } } } Output Contains 3
IndexOf. This determines the element index of a certain value in the List collection. It searches for the first position (from the start) of the value.
Note: IndexOf has two overloads. It works in the same way as string's IndexOf. It searches by value and returns the location.
C# program that uses IndexOf using System; using System.Collections.Generic; class Program { static void Main() { List<int> primes = new List<int>(new int[] { 19, 23, 29 }); int index = primes.IndexOf(23); // Exists. Console.WriteLine(index); index = primes.IndexOf(10); // Does not exist. Console.WriteLine(index); } } Output 1 -1
Contains, Exists, Find. These methods all provide searching. They vary in arguments accepted. With Predicates, we influence what elements match.
Capacity. We can use the Capacity property on List, or pass an integer to the constructor (which sets an initial capacity) to improve allocation performance.
Note: Setting a capacity sometimes improves performance by nearly two times for adding elements.
However: Adding elements, and resizing List, is not usually a performance bottleneck in programs that access data.
TrimExcess. This method's usage is limited. It reduces the memory used by lists with large capacities. And as MSDN states, TrimExcess often does nothing.
Note: It is unclear how TrimExcess feels about its status. I wouldn't want to upset its feelings.
The TrimExcess method does nothing if the list is at more than 90 percent of capacity.
BinarySearch. This implements (fittingly) the binary search algorithm. Binary search uses guesses to find the correct element faster than linear searching.
ForEach. This is a method. Sometimes we may not want to write a traditional foreach-loop. Here ForEach is useful. It accepts an Action.
Warning: Be cautious with Predicates and Actions. These objects can decrease the readability of code.
TrueForAll. This method accepts a Predicate. If the Predicate returns true for each element in the List, TrueForAll() will also return true.
Info: It checks the entire list—unless an element doesn't match and it returns false early.
Join string list. Next we use string.Join on a List of strings. This is helpful when we need to turn several strings into one comma-delimited string.
ToArray: It requires the ToArray instance method on List. This ToArray is not an extension method.
Tip: The biggest advantage of Join here is that no trailing comma is present on the resulting string.
C# that joins List using System; using System.Collections.Generic; class Program { static void Main() { // List of cities we need to join. List<string> cities = new List<string>(); cities.Add("New York"); cities.Add("Mumbai"); cities.Add("Berlin"); cities.Add("Istanbul"); // Join strings into one CSV line. string line = string.Join(",", cities.ToArray()); Console.WriteLine(line); } } Output New York,Mumbai,Berlin,Istanbul
Keys in Dictionary. We use the List constructor to get a List of keys from a Dictionary. This is a simple way to iterate over Dictionary keys or store them elsewhere.
Keys: The Keys property returns an enumerable collection of keys. But a List of these elements is more usable.
C# that converts Keys using System; using System.Collections.Generic; class Program { static void Main() { // Populate example Dictionary. var dict = new Dictionary<int, bool>(); dict.Add(3, true); dict.Add(5, false); // Get a List of all the Keys. List<int> keys = new List<int>(dict.Keys); foreach (int key in keys) { Console.WriteLine(key); } } } Output 3, 5
Insert. This is a useful but slow method. The string here is inserted at index 1. This makes it the second element. If you Insert often, consider Queue and LinkedList.
Also: A Queue may allow simpler usage of the collection in our code. This may be easier to understand.
C# that inserts into List using System; using System.Collections.Generic; class Program { static void Main() { List<string> dogs = new List<string>(); // Example list. dogs.Add("spaniel"); // Contains: spaniel. dogs.Add("beagle"); // Contains: spaniel, beagle. dogs.Insert(1, "dalmatian"); // Spaniel, dalmatian, beagle. foreach (string dog in dogs) // Display for verification. { Console.WriteLine(dog); } } } Output spaniel dalmatian beagle
InsertRange. This method inserts many elements at once. Please be aware it can impact performance in a negative way. Successive elements must be copied.
Remove. We present examples for Remove, RemoveAt, RemoveAll and RemoveRange. In general Remove operates the same way as Insert. It too hinders performance.
Sort orders the elements in the List. For strings it orders alphabetically. For integers (or other numbers) it orders from lowest to highest.
Note: Sort acts upon elements depending on type. It is possible to provide a custom method.
Reverse. With this method no sorting occurs—the original order is intact but inverted. The strings contained in the List are left unchanged.
Internally: This method invokes the Array.Reverse method. Many list methods are implemented with Array methods.
C# that uses Reverse using System; using System.Collections.Generic; class Program { static void Main() { List<string> list = new List<string>(); list.Add("anchovy"); list.Add("barracuda"); list.Add("bass"); list.Add("viperfish"); // Reverse List in-place, no new variables required. list.Reverse(); foreach (string value in list) { Console.WriteLine(value); } } } Output viperfish bass barracuda anchovy
Conversion of data types is a challenge. We can convert a List to an array of the same type using the instance method ToArray. There are examples of these conversions.
Strings: Some string methods can be used with the List class. We use, with List, the Concat and Join methods.
GetRange. This returns a range of elements in a List. This is similar to the Take and Skip methods from LINQ. It has different syntax. The result List can be used like any other List.
C# that gets ranges from List using System; using System.Collections.Generic; class Program { static void Main() { List<string> rivers = new List<string>(new string[] { "nile", "amazon", // River 2 "yangtze", // River 3 "mississippi", "yellow" }); // Get rivers 2 through 3 List<string> range = rivers.GetRange(1, 2); foreach (string river in range) { Console.WriteLine(river); } } } Output amazon yangtze
DataGridView. We can use the List type with a DataGridView. But sometimes it is better to convert the List to a DataTable. For a List of string arrays, this will work better.
Equality. Sometimes we need to test two Lists for equality, even when their elements are unordered. We can sort and then compare, or use a custom List equality method.
Note: A method can test for equality in an unordered way. But a set collection might be better.
Structs. When using List, we can improve performance and reduce memory usage with structs instead of classes. A List of structs is allocated in contiguous memory, unlike a List of classes.
However: Using structs will actually decrease performance when they are used as parameters in methods such as those on the List type.
Var keyword. This shortens lines of code, which sometimes improves readability. Var has no effect on performance, only readability for programmers.
C# that uses var with List using System.Collections.Generic; class Program { static void Main() { var list1 = new List<int>(); // <- var keyword used List<int> list2 = new List<int>(); // <- Is equivalent to } }
GetEnumerator. Programs are built upon many abstractions. With List even loops can be abstracted into an Enumerator. We can use the same methods to loop over a List or an array.
Initialize. Many syntax forms can initialize a List. Most of them have equivalent performance. In fact most are compiled to the same intermediate language instructions.
Programs are complex. They have many contexts, many paths. We use List with methods from System.Linq and System.IO. We manipulate it and serialize it.
List ConcatRemove DuplicatesSerialize List
Types: We test integer Lists, string Lists, static Lists, nested Lists and null Lists. They are used in similar ways.
Nested ListNull ListStatic List
List is a constructed, parametric type. It is powerful and performs well. It provides flexible allocation and growth, making it easier to use than arrays.
List's syntax is at first confusing. But we become used to it. In most programs lacking strict memory or performance constraints, List is ideal.