HomeSearch

C# Jagged Array Examples

Use jagged arrays to store data that comes in different sizes. Using jagged arrays can be more space efficient.

Jagged arrays.

Consider a city skyline: each tower is a different height. Suppose we represent the floors in an array. A 2D array would have wasted space. A jagged array would be best.2D Array

With jagged arrays,

we can store (efficiently) many rows of varying lengths. No space (on the tops of the skyscrapers) is wasted. Any type of data—reference or value—can be used.Array

First example.

This code is a short (but complete) program you can run in a console project. It creates a jagged array of int elements.Int, uint

Info: The program initializes some values in the jagged array. There are lots of square brackets.

Indexes: We assign the indexes to new int arrays. We only have an array of empty references—new arrays must be created for the rows.

For: We examine each item in the jagged array. We call Length first on the array of references, and then again on each inner array.

Syntax: This is different from a 2D array, which uses commas instead of pure brackets.

C# program that uses jagged arrays using System; class Program { static void Main() { // Declare local jagged array with 3 rows. int[][] jagged = new int[3][]; // Create a new array in the jagged array, and assign it. jagged[0] = new int[2]; jagged[0][0] = 1; jagged[0][1] = 2; // Set second row, initialized to zero. jagged[1] = new int[1]; // Set third row, using array initializer. jagged[2] = new int[3] { 3, 4, 5 }; // Print out all elements in the jagged array. for (int i = 0; i < jagged.Length; i++) { int[] innerArray = jagged[i]; for (int a = 0; a < innerArray.Length; a++) { Console.Write(innerArray[a] + " "); } Console.WriteLine(); } } } Output 1 2 0 3 4 5

2D arrays.

We determine how to choose between jagged arrays and 2D arrays. First ask the question: will every row in my collection have the same number of elements?

And: If so, you can consider 2D arrays, but often you have varying numbers of elements.

Performance: Jagged arrays are faster and have different syntax. They are faster because they use the "newarr", vector IL calls internally.

Zero index: The boost in performance with jagged arrays is because they are optimized for starting at 0 indexes.

IL: newarrIL Disassembler
Method that is reflected for MSIL test: C# private static void CompareIL() { int[,] twoD = new int[1, 1]; // 1 x 1 array twoD[0, 0] = 1; int[][] jag = new int[1][]; jag[0] = new int[1]; jag[0][0] = 1; // 1 x 1 jagged array }

Methods.

You can use the type of the jagged array in method signatures. They will be passed as references. This eliminates most copying. Only the reference is copied on each function call.

Benchmark, element access.

The .NET Framework has optimizations for single-dimension arrays within a jagged array. A 2D array cannot take advantage of them.

Thus: Jagged have substantial optimizations in the intermediate language level. This can be exploited to speed up programs.

C# program that benchmarks 2D, jagged arrays using System; using System.Diagnostics; class Program { const int _max = 100000; static void Main() { // Set up data. var a1 = new int[100, 100]; var a2 = new int[100][]; for (int i = 0; i < 100; i++) { a2[i] = new int[100]; } // Version 1: access 2D array. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { for (int a = 0; a < 100; a++) { for (int x = 0; x < 100; x++) { int c = a1[a, x]; } } } s1.Stop(); // Version 2: access jagged array. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { for (int a = 0; a < 100; a++) { for (int x = 0; x < 100; x++) { int c = a2[a][x]; } } } s2.Stop(); // Results. Console.WriteLine(s1.Elapsed.TotalMilliseconds); Console.WriteLine(s2.Elapsed.TotalMilliseconds); } } Output 2D array access: 1286.5545 ms Jagged array access: 486.7875 ms

Benchmark, allocation.

Consider a space of 100 by 100 elements. We can allocate 100 separate arrays in a jagged array (101 arrays total), or use a single 2D array (1).

Info: The 2D array only requires 1 allocation, and can be garbage-collected easier as well.

Results: It is faster to allocate the space in the form of a 2D array. The jagged array could be allocated lazily, which might be better.

C# program that benchmarks 2D, jagged array allocation using System; using System.Diagnostics; class Program { const int _max = 100000; static void Main() { // Version 1: create 2D array. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Create2DArray(); } s1.Stop(); // Version 2: create jagged array. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { CreateJaggedArray(); } s2.Stop(); // Print times. Console.WriteLine(s1.Elapsed.TotalMilliseconds); Console.WriteLine(s2.Elapsed.TotalMilliseconds); } static int[][] CreateJaggedArray() { var array = new int[100][]; for (int i = 0; i < 100; i++) { array[i] = new int[100]; } return array; } static int[,] Create2DArray() { var array = new int[100, 100]; return array; } } Output 2D array allocation: 202.1575 ms Jagged array allocation: 452.0066 ms

Benchmark, memory use.

A jagged array will use more memory than a 2D array assuming all sub-arrays are allocated. Here we see 2 programs that test memory use.

Program 1: This measures the memory use of a jagged array of 1000 sub-arrays. The memory size (measured with GetTotalMemory) is printed.

GC.Collect

Program 2: This measures the memory of a 2D array of the same element count as the jagged array in program 1. It uses less memory.

Info: For rectangular shapes, prefer a 2D array for best memory compactness. Fewer bytes per element are used.

Important: If your data is truly "jagged" or uneven in the lengths of subarrays, a jagged array may be far superior in memory use.

C# program that measures jagged array memory using System; class Program { static void Main() { long b1 = GC.GetTotalMemory(true); // // This program tests the memory usage of a 1000 x 100 element jagged array. // int[][] jagged = new int[1000][]; for (int i = 0; i < 1000; i++) { jagged[i] = new int[100]; } long b2 = GC.GetTotalMemory(true); jagged[0][0] = 0; Console.WriteLine("{0} bytes (jagged 1000 x 100)", b2 - b1); } } Output 416028 bytes (jagged 1000 x 100) C# program that measures 2D array memory using System; class Program { static void Main() { long b1 = GC.GetTotalMemory(true); // // This tests the memory usage of a 1000 x 100 element two-dimensional array. // int[,] array = new int[1000, 100]; long b2 = GC.GetTotalMemory(true); array[0, 0] = 0; Console.WriteLine("{0} bytes (2D 1000 x 100)", b2 - b1); } } Output 400032 bytes (2D 1000 x 100)

Performance, review.

Element access in jagged arrays is faster than in 2D arrays. But to allocate a large space at once, 2D arrays are a better choice.

A summary.

Jagged arrays are fast and easy to use once you learn the syntax. Prefer them to 2D arrays when performance is key. Be careful of excess memory usage.
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.