Search code examples
c#dictionarycode-generation

How to Output a C# Dictionary as C# code?


How can I convert a Dictionary into the C# code that would define that dictionary? (Similar to repr() in python.)

Example:

var dict = new Dictionary<int, string> {
    { 4, "a" },
    { 5, "b" }
};

Console.WriteLine(dict.ToCsharpString());

Output:

Dictionary<int, string> {
    { 4, "a" },
    { 5, "b" }
}

I'm most interested in Dictionaries containing primitive types.

Similar questions: Most efficient Dictionary.ToString() with formatting? (focused on efficiency), Is there anyway to handy convert a dictionary to String? (wants a different output format).


Solution

  • Based on Gabe's answer on a related question, here's an extension method solution:

    public static string ToCsharpString<TKey,TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> items) {
        StringBuilder str = new StringBuilder();
    
        string type_name = items.GetType().Name;
        int index = type_name.LastIndexOf('`');
        if (index == -1) {
            index = type_name.Length;
        }
        str.Append(type_name, 0, index);
        str.AppendFormat("<{0}, {1}>", typeof(TKey).Name, typeof(TValue).Name);
        str.Append(" {\n");
    
        foreach (var item in items) {
            str.AppendFormat("\t{{ {0}, {1} }},\n", ToLiteral(item.Key), ToLiteral(item.Value));
        }
        str.Append("}");
    
        return str.ToString(); 
    }
    
    static string ToLiteral(object obj) {
        string input = obj as string;
        if (input == null)
            return obj.ToString();
    
        // https://stackoverflow.com/a/324812/79125
        using (var writer = new StringWriter()) {
            using (var provider = CodeDomProvider.CreateProvider("CSharp")) {
                provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null);
                return writer.ToString();
            }
        }
    }
    

    The output is slightly different because it prints Framework Class Library type instead of primitive types (Int32 instead of int), but it works pretty well:

    Dictionary<Int32, String> {
        { 4, "a" },
        { 5, "b" },
    }
    

    Try it out.

    Room for improvement:

    • Handle recursion on embedded Dictionaries (but I don't think it's worth it due to the complexity of preventing infinite recursion).
    • Maybe printing something nicer for nonprimitive types?