Get user-friendly name for generic type in C#

Based on your edited question, you want something like this:

public static string GetFriendlyName(this Type type)
{
    if (type == typeof(int))
        return "int";
    else if (type == typeof(short))
        return "short";
    else if (type == typeof(byte))
        return "byte";
    else if (type == typeof(bool)) 
        return "bool";
    else if (type == typeof(long))
        return "long";
    else if (type == typeof(float))
        return "float";
    else if (type == typeof(double))
        return "double";
    else if (type == typeof(decimal))
        return "decimal";
    else if (type == typeof(string))
        return "string";
    else if (type.IsGenericType)
        return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">";
    else
        return type.Name;
}

You can avoid writing a recursive method by calling the recursive method that's already provided for you:

static string GetTypeName(Type type)
{
    var codeDomProvider = CodeDomProvider.CreateProvider("C#");
    var typeReferenceExpression = new CodeTypeReferenceExpression(new CodeTypeReference(type));
    using (var writer = new StringWriter())
    {
        codeDomProvider.GenerateCodeFromExpression(typeReferenceExpression, writer, new CodeGeneratorOptions());
        return writer.GetStringBuilder().ToString();
    }
}

Note that this includes the type namespaces, but excludes the assembly references. For the type in your question, the result looks like this:

System.Collections.Generic.List<System.Collections.Generic.Dictionary<int, string>>

It isn't clear to me whether that qualifies as "something like" List<Dictionary<int, string>>.


I used this code, when I needed a solution:

    public static string FriendlyName(this Type type)
    {
        if (type.IsGenericType)
        {
            var namePrefix = type.Name.Split(new [] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0];
            var genericParameters = type.GetGenericArguments().Select(FriendlyName).ToCsv();
            return namePrefix + "<" + genericParameters + ">";
        }

        return type.Name;
    }

and

    public static string ToCsv(this IEnumerable<object> collectionToConvert, string separator = ", ")
    {
        return String.Join(separator, collectionToConvert.Select(o => o.ToString()));
    }

example usage:

    var typeDisplayText = MyDataModel.GetType().FriendlyName();

...and if you're creating auto-generated developer help pages, this can also be useful, as it includes the generic parameter names:

public static string DefinitionTitle(this Type type)
    {
        if (type.IsGenericType)
        {
            var namePrefix = type.Name.Split(new[] { '`' }, StringSplitOptions.RemoveEmptyEntries)[0];
            var genericParameters = type.GetGenericArguments().Select(a => a.Name).ToCsv();
            return namePrefix + "<" + genericParameters + ">";
        }

        return type.Name;
    }

example usage:

    var typeDefinitionText = typeof(Dictionary<,>).DefinitionTitle());