Table of Contents | |
What Is the SortedList in C#?
C# SortedList<TKey, TValue> represents a generic sorted collection class, which is used to store data in a key/value pair format that is sorted by key. Key must be unique and cannot be null whereas value can be duplicate and null. Each item in the SortedList is treated as KeyValuePair<TKey, TValue> structure that associates a key to a value. You can get the associated value using the unique key as an index with the indexer method. Each item can be retrieved as a KeyValuePair<TKey, TValue> object.
C# SortedList can be implemented with the SortedList<TKey, TValue> class in the System.Collections.Generic namespace, where TKey and TValue are type parameters.
Properties and Methods of SortedList Class
Mostly used methods of the SortedList<> class to perform different operations are listed below.
You can declare and initialize C# SortedList as in the following code.
using
Statement
To work with C# SortedList, you need to add the following namespace at the beginning your code:
using System.Collections.Generic;
How Do You Create a SortedList in C#?
You can create C# SortedList using either one or two statements.
Declare and Initialize C# SortedList Using Two Statements
TKey and TValue are the generic data type parameters, where TKey is the type of the Key and TValue is the type of the value. This part of the declaration indicates that the class will work with a certain type.
SortedList<TKey, TValue> sortedListName; // declaration
You use new keyword with default constructor to initialize an empty sorted list.
sortedListName = new SortedList<TKey, TValue>(); // initialization
You can set the initial capacity of a sorted list by specifying the number of items in parentheses () when a list is created. If the number of items in the list exceeds the capacity, the capacity is automatically doubled to accommodate more items.
sortedListName = new SortedList<TKey, TValue>(capacity);
The capacity can be decreased by calling TrimExcess method or by setting the Capacity property explicitly.
Declare and Initialize C# SortedList on a Single Line
SortedList<TKey, TValue> sortedListName = new SortedList<TKey, TValue>(); // declaration & initialization
Use of var keyword to infer its type from the value that’s assigned to it.
var sortedListName = new SortedList<TKey, TValue>();
C# Collection Initializers
You can assign values to collections using collection initializer syntax introduced in C# 3.0. It is a shortened syntax to create an instance of a collection. With a collection initializer, the values can be assigned all at once during the declaration using curly brackets notation. When the C# compiler encounters a collection initializer, it’ll replace the shorthand initializer syntax by appropriate method calls to the Add method.
Notice that because each item of a sorted list consists of two values, each item is enclosed in braces within the outer braces. Key names must be unique when populating the collection.
Here, you can specify each key/value pair as an anonymous type in the initializer list, like this:
SortedList<int, string> planets = new SortedList<int, string>() {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
If no parameters are passed in the constructor, then parentheses () following the data type are optional.
SortedList<int, string> planets = new SortedList<int, string> {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
The following collection initializer uses C# object initializers to initialize objects of the Planet class. Individual object initializers are enclosed in braces and separated by commas. Here, you are using int data type as the key (key can be any type) and a Planet type as the value.
var planets = new SortedList<int, Planet> {
{ 101, new Planet() { Id = 1, Name = "Mercury" } },
{ 102, new Planet() { Id = 2, Name = "Venus" } },
{ 103, new Planet() { Id = 3, Name = "Earth" } }
};
C# Index Initializers (indexer notation)
C# 6 introduced a new feature called index initializer if a collection supports indexing, where you don’t need key and value within braces { }. Instead, you use the key within brackets [ ] followed by assignment operator (=) to assign value to that key.
Note: The new initializer syntax calls the indexer method to add and replace items to the collection.
//With an index initializer inside a collection initializer
SortedList<int, string> planets = new SortedList<int, string>()
{
[1] = "Mercury",
[2] = "Venus",
[3] = "Earth"
};
To make your code more readable, I recommend that you use the indexer notation wherever possible to initialize C# SortedList type.
Add Items to C# SortedList
SortedList<int, string> planets = new SortedList<int, string>();
Add()
Use the Add method to add an item to the list. When you add an item to a sorted list, you specify the key along with the value assigned to that key. The SortedList automatically ensures that the items in the set are sorted when you insert or remove items.
Signature: void Add(TKey key, TValue value)
//With separated statements
planets.Add(2, "Venus");
planets.Add(1, "Mercury");
planets.Add(3, "Earth");
Output
1, Mercury
2, Venus
3, Earth
Every key in a SortedList<TKey, TValue> must be unique, meaning you cannot use duplicate keys in the list. Any attempt to do that will result an exception ArgumentException with the message ‘An item with the same key has already been added. Key: 3’
// Different key but same value
planets.Add(4, "Earth");
//Same key but different value
planets.Add(3, "Mars"); // Exception
Using add method to add individual objects of Planet class.
SortedList<int, Planet> planets = new SortedList<int, Planet>();
var jupiter = new Planet();
jupiter.Id = 1;
jupiter.Name = "4 line: Mercury";
planets.Add(101, jupiter);
//Above 4 lines vs below 1 line syntax. Same result
planets.Add(102, new Planet() { Id = 2, Name = "1 line: Mercury" });
Output
101, 1 : 4 line: Mercury
102, 2 : 1 line: Mercury
Key Indexer to Add and Update Items
If a key does not exist, setting the indexer for that key adds a new key/value pair in the sorted list.
planets = new SortedList<int, string>();
// using array notation
planets[1] = "Mercury";
planets[2] = "Venus";
planets[3] = "Earth";
Use key indexer to update value associated with the key.
planets[3] = "Earth - Updated";
Output
1, Mercury
2, Venus
3, Earth- Updated
Remove Items from C# SortedList
SortedList<int, string> planets = new SortedList<int, string> {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
Remove()
The Remove method removes a particular item from the list. This method takes in one argument and removes the first occurrence of that argument. You need to pass the key to remove.
Signature: bool Remove(TKey key)
planets.Remove(2);
Output
1, Mercury
3, Earth
RemoveAt()
The RemoveAt method removes an item from a specific location in the list by passing an index.
Signature: void RemoveAt(int index)
planets.RemoveAt(1);
Output
1, Mercury
3, Earth
Clear()
The Clear method removes all the items in a list and sets its Count property to zero.
Signature: void Clear()
planets.Clear();
C# SortedList Methods
SortedList<int, string> planets = new SortedList<int, string> {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
ContainsKey()
You can test whether a SortedList<TKey, TValue> collection already contains a particular key by using the ContainsKey method, which returns Boolean (True/False) value.
Signature: bool ContainsKey(TKey key)
planets.ContainsKey(2); // Returns True
Output
True
ContainsValue()
Method checks and returns Boolean (True/False) value that indicates whether or not the sorted list contains the specified value.
Signature: bool ContainsValue(TValue value)
planets.ContainsValue("Venus"); // Returns True
Output
True
IndexOfKey()
Method checks entire SortedList<TKey, TValue> for the provided key and returns zero-based index value.
Signature: int IndexOfKey(TKey key)
planets.IndexOfKey(3); //Returns 2
IndexOfValue()
Method checks SortedList<TKey, TValue> for the first occurrence of the provided value and returns zero-based index value.
Signature: int IndexOfValue(TValue value)
planets.IndexOfValue("Venus"); //Returns 1
TryGetValue()
Gets the value associated with the specified key.
Signature: bool TryGetValue(TKey key, out TValue value)
string value = string.Empty;
planets.TryGetValue(3, out value);
Output
Earth
// Or
if (planets.TryGetValue(4, out value))
Console.WriteLine(value);
else
Console.WriteLine("Key not found");
Output
Key not found
TrimExcess()
Resizes the capacity to the actual number of items in the SortedList<TKey, TValue>, if that number is less than 90 percent of current capacity.
Signature: void TrimExcess()
var planets = new SortedList<int, string>(6);
Console.WriteLine($"Capacity : {planets.Capacity}"); // Capacity before TrimExcess() is 6
planets.Add(1, "Mercury");
planets.Add(2, "Venus");
planets.Add(3, "Earth");
planets.TrimExcess();
Console.WriteLine($"Capacity : {planets.Capacity}"); // Capacity after TrimExcess() is 3
C# SortedList Properties
SortedList<int, string> planets = new SortedList<int, string> {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
Count
To get the total number of key/value pairs contained in the SortedList<TKey, TValue>, use the Count property.
planets.Count; // Returns 3
Capacity
The Capacity property gets or sets the number of items a SortedList<TKey, TValue> can hold. It is automatically increased as required when items are added to it.
The default capacity of a list is 0; if initialized as an empty list. As you can see in the following example.
planets = new SortedList<int, string>();
planets.Capacity; //Returns 0
The capacity automatically assigned to a list is 4, even if initialized with a single item. As soon as the number of items in a list exceeds 4, the list is resized to accommodate more items. With every resizes the capacity is automatically doubled from 4 to 8, 16, 24 etc. Check the below example.
planets = new SortedList<int, string>() { { 1, "Mercury" } };
planets.Capacity; //Returns 4
Set the initial capacity of a sorted list by specifying the number in parentheses () when a list is created.
planets = new SortedList<int, string>(7); //Constructor
You can set the capacity later in the code, once sorted listed is created.
planets = new SortedList<int, string>();
planets.Capacity; // Default initial capacity is 0
planets.Capacity = 5; //Set capacity to 5
If you set the capacity after initialization of a sorted list and the number of items exceeds that capacity, an ArgumentOutOfRangeException exception is thrown with the message ‘capacity was less than the current size.’
planets = new SortedList<int, string>() {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" },
{ 4, "Mars" }
};
planets.Capacity = 3; // Set capacity to 3
Keys
To get a collection containing the keys in the SortedList<TKey, TValue>, in sorted order, use the Keys property.
Note: Keys property returns IList.
foreach (var key in planets.Keys)
Console.WriteLine(key);
// Or copy all the keys and then iterate
IList keys = planets.Keys;
foreach (var key in keys)
Console.WriteLine(key);
Output
1
2
3
Values
To get a collection containing the values in the SortedList<TKey, TValue>, use the Values property.
Note: Values property returns IList.
foreach (var value in planets.Values)
Console.WriteLine(value);
// Or copy all the values and then iterate
IList values = planets.Values;
foreach (var value in values)
Console.WriteLine(value);
Output
Mercury
Venus
Earth
Indexer to Access Individual C# SortedList Item
SortedList<int, string> planets = new SortedList<int, string>() {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
You can access the sorted list items individually by using indexer method. Key is used inside the square brackets [ ] to get the associated value.
Syntax
SortedListName[key];
Code
planets[3];
Output
Earth
The Values property is also an efficient way to retrieve values by index.
Syntax
SortedListName.Values[Index];
Code
planets.Values[1];
Output
Venus
The Keys property is an efficient way to retrieve keys by index.
Syntax
SortedListName.Keys[Index];
Code
planets.Keys[1]; // Venus key
Output
2
If you try to access an item with an indexer and passing a key that does not exist, an exception of type KeyNotFoundException is thrown with the message ‘The given key ‘4’ was not present in the dictionary.’.
planets[4]; // throw exception
To avoid that exception, you can use the method ContainsKey, which returns true if the key passed exists in the collection, or you can invoke the method TryGetValue, which tries to get the value but doesn’t throw an exception if key isn’t found:
// ContainsKey() method
if (planets.ContainsKey(4)) // Replace 4 with 3
Console.WriteLine(planets[4]);
else
Console.WriteLine("Key not found");
// TryGetValue() method
string value = "";
if (planets.TryGetValue(4, out value)) // Replace 4 with 3
Console.WriteLine(value);
else
Console.WriteLine("Key not found");
Output
Key not found
Processing C# SortedList with Loops
The first statement declares a sorted list named planets that contains 3 values.
SortedList<int, string> planets = new SortedList<int, string>() {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
Note: It doesn’t matter where you are modifying the collection. If a collection is modified while you are enumerating its members, you get exception.
foreach
Loop
You use C# foreach Loop to iterate through a SortedList<TKey, TValue>. Each item returned is a KeyValuePair<TKey, TValue> object, which contains a copy of the key and value elements of an item in the SortedList <TKey, TValue> collection. You can access each element through the Key and Value property.
Note: The foreach statement only allows reading from, not writing to, the collection.
foreach (var planet in planets)
Console.WriteLine($"{planet.Key}, {planet.Value}");
Output
1, Mercury
2, Venus
3, Earth
You cannot use the iteration to modify the contents of the collection. Any attempt to do that will result an exception of type InvalidOperationException with the message ‘Collection was modified; enumeration operation may not execute.’
foreach (var planet in planets)
{
if (planet.Key == 2)
planets.Remove(planet.Key); // Throw an exception here
}
Solution
Copy the keys in a temp list (or another collection) and then iterate through this temp list to modify the collection:
//Populate all the keys in a temp list
var keys = new List(planets.Keys); // Populated with 1, 2, 3
// Iterate through keys and remove the item from the collection (planets)
foreach (var key in keys)
{
if (key == 2)
planets.Remove(key); // Removed { 2, Venus }
if (planets.ContainsKey(key))
Console.WriteLine($"{key}, {planets[key]}");
}
Output
1, Mercury
3, Earth
for
Loop
Here’s an example that shows how you can iterate through the contents of a sorted list collection using C# for Loop:
for (int i = 0; i < planets.Count; i++)
Console.WriteLine($"{planets.Keys[i]}, {planets.Values[i]}");
Output
1, Mercury
2, Venus
3, Earth
Processing C# SortedList with LINQ
You can use LINQ to process SortedList collection.
SortedList<int, string> planets = new SortedList<int, string>() {
{ 1, "Mercury" },
{ 2, "Venus" },
{ 3, "Earth" }
};
// Namespace required
using System.Linq;
// LINQ Method Expression
var planet = planets.Where(p => p.Key == 2).SingleOrDefault();
Console.WriteLine($"{planet.Key}, {planet.Value}");
// LINQ Query Expression
var planet = (from p in planets where p.Key == 3 select p).SingleOrDefault();
Console.WriteLine($"{planet.Key}, {planet.Value}");
Output
2, Venus
3, Earth
C# SortedList Examples
This statement declares and initializes a sorted list of 3 objects. Once the list is created, you can add items to the list with an Add method.
SortedList<int, char> alphabet = new SortedList<int, char>() {
{ 2, 'B' },
{ 1, 'A' },
{ 3, 'C' }
};
//Add() to add item, auto sorted by key
alphabet.Add(4, 'D');
alphabet.Add(5, 'E');
// Add item by Key indexer
alphabet[6] = 'F';
alphabet[7] = 'G';
// Update item value associated with key 7 from G to H
alphabet[7] = 'H';
foreach (var letter in alphabet)
Console.WriteLine($"{letter.Key}, {letter.Value}");
//Reset items
alphabet = new SortedList<int, char>() {
{ 1, 'A' },
{ 2, 'B' },
{ 3, 'C' },
{ 4, 'D' },
{ 5, 'E' },
{ 6, 'F' },
{ 7, 'G' }
};
//Count to get total items
Console.WriteLine(alphabet.Count); // Prints 7
//Capacity to get number of items a list can hold
Console.WriteLine(alphabet.Capacity); // Prints 8
//Keys, Values
foreach (var key in alphabet.Keys)
Console.WriteLine(key);
foreach (var value in alphabet.Values)
Console.WriteLine(value);
//Get value by key indexer
Console.WriteLine(alphabet[1]); // Prints A
Console.WriteLine(alphabet[5]); // Prints E
// foreach loop
foreach (var letter in alphabet)
Console.WriteLine($"{letter.Key}, {letter.Value}");
//for loop
for (int i = 0; i < alphabet.Count; i++)
Console.WriteLine($"{alphabet.Keys[i]}, {alphabet.Values[i]}");
//ContainsValue(), ContainsKey()
Console.WriteLine(alphabet.ContainsValue('B')); // Prints True
Console.WriteLine(alphabet.ContainsKey(10)); // Prints False
//Reset items
alphabet = new SortedList<int, char>() {
{ 1, 'A' },
{ 2, 'B' },
{ 3, 'C' },
{ 4, 'D' },
{ 5, 'E' },
{ 6, 'F' },
{ 7, 'G' }
};
// Remove(), RemoveAt()
alphabet.Remove(2); //By Key
alphabet.RemoveAt(3); // By Index
foreach (var letter in alphabet)
Console.WriteLine($"{letter.Key}, {letter.Value}");
// IndexOfKey(), IndexOfValue()
alphabet.IndexOfKey(2); //By Index by Key
alphabet.IndexOfValue('B'); // Return Index by Value
foreach (var letter in alphabet)
Console.WriteLine($"{letter.Key}, {letter.Value}");
//Clear() to remove all the items
alphabet.Clear();
Console.WriteLine(alphabet.Count); // Prints 0
SortedList<int, string> Vegetables = new SortedList<int, string> {
{ 2, "Carrot" },
{ 1, "Cucumber" },
{ 3, "Tomato" },
{ 4, "Onion" },
{ 5, "Green Pepper" }
};
var integerValues = new SortedList<int, int>(3);
integerValues.Add(1, 10);
integerValues.Add(2, 20);
integerValues.Add(3, 30);
//Code that creates a sorted list to holds decimal values
SortedList<int, decimal> decimalValues = new SortedList<int, decimal>();
decimalValues[1] = 13.2m;
decimalValues[2] = 20.74m;
decimalValues[3] = 8.34m;