C# – Merge two dictionaries in-place

When you merge two dictionaries, you can either merge them in-place, or create a new dictionary and copy the values over to it.

The following extension method does an in-place merge of two dictionaries. It loops through items in the right dictionary, adding them to the left dictionary. When duplicate keys exist, it’s keeping the value from the left (instead of throwing an ArgumentException, or keeping the value from the right).

public static class DictUtils
{
	public static Dictionary<Key, Value> MergeInPlace<Key, Value>(this Dictionary<Key, Value> left, Dictionary<Key, Value> right)
	{
		if (left == null)
		{
			throw new ArgumentNullException("Can't merge into a null dictionary");
		}
		else if (right == null)
		{
			return left;
		}

		foreach (var kvp in right)
		{
			if (!left.ContainsKey(kvp.Key))
			{
				left.Add(kvp.Key, kvp.Value);
			}
		}

		return left;
	}
}
Code language: C# (cs)

Note: Even though this is doing an in-place merge, it’s returning a dictionary. This is so you can use this in a fluent manner, for example: left.MergeInPlace(dict1).MergeInPlace(dict2).Count().

Unit tests for MergeInPlace()

Here are unit tests that exercise all the behavior in the MergeInPlace() method.

[TestClass()]
public class DictUtilsTests
{
	[TestMethod()]
	public void MergeInPlaceTest_WhenLeftNull_ThrowsNullArgument()
	{
		//arrange
		Dictionary<string, string> left = null;
		var right = new Dictionary<string, string>();

		//act & assert
		Assert.ThrowsException<ArgumentNullException>(() => left.MergeInPlace(right));
	}
	[TestMethod()]
	public void MergeInPlaceTest_WhenRightNull_ReturnsLeft()
	{
		//arrange
		var left = new Dictionary<string, string>();
		Dictionary<string, string> right = null;

		//act
		var merged = left.MergeInPlace(right);

		//assert
		Assert.AreSame(left, merged);
	}
	[TestMethod()]
	public void MergeInPlaceTest_WhenItemInRight_MergesIntoLeft()
	{
		//arrange
		var testKey = "TEST";
		var testValue = "1";
		var left = new Dictionary<string, string>();
		var right = new Dictionary<string, string>()
		{
			[testKey] = testValue
		};

		//act
		left.MergeInPlace(right);

		//assert
		Assert.AreEqual(testValue, left[testKey]);
	}
	[TestMethod()]
	public void MergeInPlaceTest_WhenItemInLeft_StillInLeft()
	{
		//arrange
		var testKey = "TEST";
		var testValue = "1";
		var left = new Dictionary<string, string>()
		{
			[testKey] = testValue
		};
		var right = new Dictionary<string, string>();

		//act
		left.MergeInPlace(right);

		//assert
		Assert.AreEqual(testValue, left[testKey]);
	}
	[TestMethod()]
	public void MergeInPlaceTest_ItemsInLeftAndRight_PutsAllInLeft()
	{
		//arrange
		var leftTestKey = "TEST";
		var leftTestValue = "1";
		var left = new Dictionary<string, string>()
		{
			[leftTestKey] = leftTestValue
		};
		var rightTestKey = "TEST2";
		var rightTestValue = "2";
		var right = new Dictionary<string, string>()
		{
			[rightTestKey] = rightTestValue
		};

		var expected = new Dictionary<string, string>()
		{
			[leftTestKey] = leftTestValue,
			[rightTestKey] = rightTestValue
		};

		

		//act
		left.MergeInPlace(right);

		//assert
		CollectionAssert.AreEqual(expected, left);
	}
	[TestMethod()]
	public void MergeInPlaceTest_WhenKeyInBothLeftAndRight_TakesTheValueFromLeft()
	{
		//arrange
		var testKey = "TEST";
		var leftTestValue = "1";
		var left = new Dictionary<string, string>()
		{
			[testKey] = leftTestValue
		};
		var rightTestValue = "2";
		var right = new Dictionary<string, string>()
		{
			[testKey] = rightTestValue
		};

		//act
		left.MergeInPlace(right);

		//assert
		Assert.AreEqual(leftTestValue, left[testKey]);
	}
}
Code language: C# (cs)

Why not use Linq Union() or Concat()?

You might be wondering why you’d need to write your own merge method, instead of using the Linq Union() / Concat() methods.

The reason is because they can’t handle duplicate keys.

For example, let’s say I have two dictionaries that have the same key “TEST”.

var testKey = "TEST";
var testValueLeft = "1";
var testValueRight = "2";
var left = new Dictionary<string, string>()
{
	[testKey] = testValueLeft
};
var right = new Dictionary<string, string>()
{
	[testKey] = testValueRight
};

var merged = left.Union(right).ToDictionary(t => t.Key, t => t.Value);
Code language: C# (cs)

This throws System.ArgumentException: An item with the same key has already been added.

In the MergeInPlace() method I showed in this article, when the key exists in both dictionaries, it takes the value from the left. Because you’re writing your own merging logic, you can make it handle duplicates however you want.

With the Linq methods, they simply don’t handle duplicate keys at all.