# TryGetValue Vs ContainsKey With Indexer

## Introduction

TryGetValue is a combination of ContainsKey with Indexer but how do these two methods compare with one another? We're going to look at the use case and when it's best to use them. Also, we're going to look at the speed. They are both very fast but does one edge out another and which cases. Let's look at the example.

### Summary Table

Analysis TypeTryGetValueContainsKey With Indexer
Use CaseLots of retrieve valuesTest if keys exist
PerformanceApproaches O(1)Approaches O(1)
Lines Of Code45

### Use Case Code Example

This code works by using the TryGetValue method to get the value from the dictionary by the provided key. Then the second if statement has the two step process the ContainsKey method ckeck on the dictionary and if it is true then use the dictionary indexer to return the value with provided key.

``````Dictionary<string, double> mathEquationsConstantsDict = new Dictionary<string, double>()
{
{ "Euler's identity", -1 },
{ "Pythagorean theorem", 5 },
{ "Newton's second law", 9.81 },
{ "Planck's constant", 6.62607015e-34 },
{ "Boltzmann constant", 1.380649e-23 },
{ "Speed of light", 299792458 },
{ "Golden ratio", 1.61803398875 },
{ "Archimedes' principle", 1000 },
{ "Coulomb's law", 8.99e9 },
{ "Ideal gas constant", 8.31446261815324 },
{ "Gaussian integral", 1.77245385091 },
{ "Heisenberg uncertainty principle", 5.272859e-35 },
{ "Riemann hypothesis", 0.5 },
{ "De Broglie wavelength", 1.227e-10 },
{ "Dirac delta function", double.PositiveInfinity },
{ "Euler's number", 2.71828182846 },
{ "Planck length", 1.616255e-35 },
{ "Catalan's constant", 0.915965594177219 },
{ "Gamma function", 1 }
};

string keyForTryGetValue = "Speed of light";
if(mathEquationsConstantsDict.TryGetValue(keyForTryGetValue, out double mathConstant1))
{
Console.WriteLine(\$"TryGetValue:key{keyForTryGetValue}, value:{mathConstant1}");
//use value in some logic
}

string keyForContainsKey = "Boltzmann constant";
if(mathEquationsConstantsDict.ContainsKey(keyForContainsKey))
{
double mathConstant2 = mathEquationsConstantsDict[keyForContainsKey];//Get value by using dictionary indexer
Console.WriteLine(\$"ContainsKey:key{keyForContainsKey}, value:{mathConstant2}");
//use value in some logic
}
``````
###### Code Output
``````TryGetValue:keySpeed of light, value:299792458
ContainsKey:keyBoltzmann constant, value:1.380649E-23
``````

### Performance

Next we'll compare the performance of both the methods TryGetValue and ContainsKey with Indexer to see how they compare in performance. This test consists of 10 tests which are averaged. Each test has 100 function calls of the test method. Each test method has list of keys to loop through which 1 million.

Test Parameters
Test ParametersTotal
Tests10
Function Calls Per Test100
Objects Per Function Call1 Million

#### TryGetValue Speed Test Code

This code loop through all the keys in the dictionary and calls the TryGetValue method to get the value for item in dictionary.

``````void TestMethod(Dictionary<string, string> dictionary)
{
foreach (string key in keysList)
{
if (dictionary.TryGetValue(key, out string value))
{
//use value in some logic
}
}
}
``````
###### Code Output
``````Test 1:Function Calls:100, In 0m 7s 484ms
Test 2:Function Calls:100, In 0m 7s 307ms
Test 3:Function Calls:100, In 0m 6s 876ms
Test 4:Function Calls:100, In 0m 6s 887ms
Test 5:Function Calls:100, In 0m 6s 993ms
Test 6:Function Calls:100, In 0m 6s 905ms
Test 7:Function Calls:100, In 0m 6s 901ms
Test 8:Function Calls:100, In 0m 6s 929ms
Test 9:Function Calls:100, In 0m 6s 726ms
Test 10:Function Calls:100, In 0m 6s 658ms
TryGetValue Method Average Speed:6967ms, In 10 Tests
``````

We see that this has a baseline of about 7 seconds. We can compare this to the ContainsKey with indexer method. Next, let's see how ContainsKey compares to the same test.

Full TryGetValue Speed Test Code
``````
using System.Diagnostics;

int numberOfTests = 10;//Number of tests
int numberOfFunctionCalls = 100;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//Number test objects
int lengthOfRandomString = 50;
string testName = "TryGetValue Method";//Test name to print to average
List<string> keysList = new List<string>();
void TestMethod(Dictionary<string, string> dictionary)
{
foreach (string key in keysList)
{
if (dictionary.TryGetValue(key, out string value))
{
//use value in some logic
}
}
}

List<double> testSpeedList = new List<double>();
for (int testIndex = 0; testIndex < numberOfTests; testIndex++)
{
}
Console.WriteLine(\$"{testName} Average Speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} Tests");

double StartTest(int testIndex)
{
Stopwatch stopwatch = new Stopwatch();
Dictionary<string, string> testData = GetDictionaryData();//Get intial random generated data
for (int i = 0; i < numberOfFunctionCalls; i++)
{
stopwatch.Start();//Start the Stopwatch timer
TestMethod(testData);//
stopwatch.Stop();//Stop the Stopwatch timer
}
stopwatch.Stop();//Stop the Stopwatch timer
Console.WriteLine(\$"Test {testIndex + 1}:Function Calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
return stopwatch.Elapsed.TotalMilliseconds;
}

Dictionary<string, string> GetDictionaryData()
{
Dictionary<string, string> testData = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
keysList = new List<string>();
for (int i = 0; i < numberOfObjectsToCreate; i++)
{
string key = GenerateRandomString(lengthOfRandomString);
if (!testData.ContainsKey(key))
{
string value = GenerateRandomString(lengthOfRandomString);
testData[key] = value;
}
}
return testData;
}
string GenerateRandomString(int length)
{
Random random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}

``````

#### ContainsKey With Indexer Speed Test Code

``````void TestMethod(Dictionary<string, string> dictionary)
{
foreach (string key in keysList)
{
if (dictionary.ContainsKey(key))
{
string value = dictionary[key];
//use value in some logic
}
}
}
``````
###### Code Output
``````Test 1:Function Calls:100, In 0m 9s 713ms
Test 2:Function Calls:100, In 0m 9s 711ms
Test 3:Function Calls:100, In 0m 9s 763ms
Test 4:Function Calls:100, In 0m 9s 920ms
Test 5:Function Calls:100, In 0m 10s 208ms
Test 6:Function Calls:100, In 0m 10s 16ms
Test 7:Function Calls:100, In 0m 9s 851ms
Test 8:Function Calls:100, In 0m 9s 834ms
Test 9:Function Calls:100, In 0m 10s 299ms
Test 10:Function Calls:100, In 0m 9s 441ms
ContainsKey Method Average Speed:9876ms, In 10 Tests
``````
Full ContainsKey With Indexer Speed Test Code
``````
using System.Diagnostics;

int numberOfTests = 10;//Number of tests
int numberOfFunctionCalls = 100;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//Number test objects
int lengthOfRandomString = 50;
string testName = "ContainsKey Method";//Test name to print to average
List<string> keysList = new List<string>();
void TestMethod(Dictionary<string, string> dictionary)
{
foreach (string key in keysList)
{
if (dictionary.ContainsKey(key))
{
string value = dictionary[key];
//use value in some logic
}
}
}

List<double> testSpeedList = new List<double>();
for (int testIndex = 0; testIndex < numberOfTests; testIndex++)
{
}
Console.WriteLine(\$"{testName} Average Speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} Tests");

double StartTest(int testIndex)
{
Stopwatch stopwatch = new Stopwatch();
Dictionary<string, string> testData = GetDictionaryData();//Get intial random generated data
for (int i = 0; i < numberOfFunctionCalls; i++)
{
stopwatch.Start();//Start the Stopwatch timer
TestMethod(testData);//
stopwatch.Stop();//Stop the Stopwatch timer
}
stopwatch.Stop();//Stop the Stopwatch timer
Console.WriteLine(\$"Test {testIndex + 1}:Function Calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
return stopwatch.Elapsed.TotalMilliseconds;
}

Dictionary<string, string> GetDictionaryData()
{
Dictionary<string, string> testData = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
keysList = new List<string>();
for (int i = 0; i < numberOfObjectsToCreate; i++)
{
string key = GenerateRandomString(lengthOfRandomString);
if (!testData.ContainsKey(key))
{
string value = GenerateRandomString(lengthOfRandomString);
testData[key] = value;
}
}
return testData;
}
string GenerateRandomString(int length)
{
Random random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}

``````

### Conclusion

Overall RankMethodSpeed
1TryGetValue6967ms
2ContainsKey With Indexer9876ms

Even though these methods are very fast. TryGetValue has a solid edge over ContainsKey with Indexer of 2 to 3 seconds improvement. TryGetValue is better in performance and it has less lines of code. So you going to be using the value in any way then you should TryGetValue.

For ContainsKey, you should be using it if you're only doing a check if the key exists and then doing some logic. Don't use it to check if the key is there then get the value as it is slower than TryGetValue.

Know any other ways to compare TryGetValue to ContainsKey with Indexer? Let me know in the comments below.