C#
object conversion
Dictionary<TKey
TValue>
programming
C# dictionary

How to convert object to DictionaryTKey, TValue in C?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

In C#, "convert an object to a dictionary" usually means turning an object's public properties into key-value pairs. The important detail is that most objects naturally map to Dictionary<string, object?>, not to an arbitrary Dictionary<TKey, TValue>, because property names are strings and property values may have mixed types.

The Common Case: Dictionary<string, object?>

If you have a plain object and want a dictionary of property names to values, reflection is the standard approach:

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Reflection;
5
6public static class ObjectDictionaryExtensions
7{
8    public static Dictionary<string, object?> ToPropertyDictionary(this object source)
9    {
10        if (source == null) throw new ArgumentNullException(nameof(source));
11
12        return source.GetType()
13            .GetProperties(BindingFlags.Instance | BindingFlags.Public)
14            .Where(p => p.CanRead)
15            .ToDictionary(
16                p => p.Name,
17                p => p.GetValue(source)
18            );
19    }
20}
21
22public class User
23{
24    public int Id { get; set; }
25    public string Name { get; set; } = "";
26    public bool IsAdmin { get; set; }
27}
28
29var user = new User { Id = 42, Name = "Mina", IsAdmin = true };
30var dict = user.ToPropertyDictionary();
31
32Console.WriteLine(dict["Name"]);

This is useful for logging, templating, dynamic APIs, or building query parameters where property names become string keys.

Why Dictionary<TKey, TValue> Is Usually Too General

An object does not normally contain enough information to become any arbitrary Dictionary<TKey, TValue>. For example, property names are strings, not Guid or int, and property values may be a mix of string, bool, decimal, and nested objects.

That means you need to decide:

  • What should become the key.
  • What should become the value.
  • How to convert types safely.

If you truly need Dictionary<TKey, TValue>, you usually need selector functions instead of raw reflection.

Building A Typed Dictionary With Selectors

Suppose you have a collection of objects and want one property to be the key:

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5public class Product
6{
7    public int Id { get; set; }
8    public string Name { get; set; } = "";
9    public decimal Price { get; set; }
10}
11
12var products = new List<Product>
13{
14    new Product { Id = 1, Name = "Keyboard", Price = 49.99m },
15    new Product { Id = 2, Name = "Mouse", Price = 19.99m }
16};
17
18Dictionary<int, string> productNames = products.ToDictionary(
19    p => p.Id,
20    p => p.Name
21);
22
23Console.WriteLine(productNames[1]);

This is the more honest interpretation of Dictionary<TKey, TValue> in C#. You are not converting one arbitrary object directly. You are projecting data into a dictionary shape with explicit rules.

Handling Nested Objects And Null Values

Reflection only gets top-level property values unless you recursively walk the object graph yourself. For example:

csharp
1public class Address
2{
3    public string City { get; set; } = "";
4}
5
6public class Customer
7{
8    public string Name { get; set; } = "";
9    public Address Address { get; set; } = new Address();
10}

Using the reflection helper on Customer gives a dictionary where Address is still an Address object. If you need a fully flattened dictionary, write that behavior explicitly because recursion rules, collection handling, and property naming quickly become application-specific.

A Safer Reusable Helper

You can make the reflection helper slightly more robust by skipping indexers and allowing custom property-name comparison:

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Reflection;
5
6public static class DictionaryConverter
7{
8    public static Dictionary<string, object?> ToDictionary(object source, StringComparer comparer)
9    {
10        if (source == null) throw new ArgumentNullException(nameof(source));
11
12        var dictionary = new Dictionary<string, object?>(comparer);
13
14        foreach (var property in source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
15        {
16            if (!property.CanRead || property.GetIndexParameters().Length > 0)
17            {
18                continue;
19            }
20
21            dictionary[property.Name] = property.GetValue(source);
22        }
23
24        return dictionary;
25    }
26}

This keeps the helper practical without pretending that every object can cleanly become every possible generic dictionary.

Common Pitfalls

The biggest mistake is assuming one arbitrary object can be converted to any Dictionary<TKey, TValue> without defining how keys and values should be derived. In most cases, the correct type is Dictionary<string, object?>.

Another pitfall is using reflection in hot paths without thinking about cost. Reflection is flexible, but repeated conversion of large objects can become expensive. If performance matters, cache property metadata or use source-generated serializers and mappers.

Developers also often ignore duplicate keys when projecting collections with ToDictionary. If two objects produce the same key, the conversion throws. Decide whether duplicates should fail, overwrite, or group.

Finally, nested objects need explicit handling. A shallow property dictionary is not the same thing as a flattened JSON-like representation.

Summary

  • A plain object usually maps naturally to Dictionary<string, object?>.
  • Reflection is the standard way to convert public properties into key-value pairs.
  • 'Dictionary<TKey, TValue> requires explicit key and value mapping rules.'
  • For collections, Enumerable.ToDictionary is often the right tool.
  • Be deliberate about nulls, duplicates, nested objects, and reflection cost.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.