0

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).

idbrii
  • 10,975
  • 5
  • 66
  • 107
  • Why don't you use a JSON serializer/ deserializer as described in this [answer](https://stackoverflow.com/a/25797924/1974344)? JSON is really easy to process in .NET/C#. – Odrai Jul 18 '19 at 18:52
  • Might the `Dictionary` have some form of custom comparer (e.g. case insensitive)? – mjwills Jul 18 '19 at 21:34
  • @Odrai: I don't think a JSON serializer will output to C#? I use this for two purposes: quick debug logs (where C# is a familiar form for the data) and generating data that I later insert into my code. – idbrii Jul 18 '19 at 22:53
  • `How can I convert a Dictionary into the C# code that would define that dictionary?` If you are trying to generate the code that created a dictionary, and the original code **used a custom comparer** are you expecting the generated code to also include the custom comparer? – mjwills Jul 18 '19 at 23:14
  • @mjwills: No. I'm just looking for the keys & values to be the same. Not the configuration of the dictionary. – idbrii Jul 19 '19 at 21:27

1 Answers1

2

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?
idbrii
  • 10,975
  • 5
  • 66
  • 107