Get type name without any generics info

Viewed 8546

If I write:

var type = typeof(List<string>);
Console.WriteLine(type.Name);

It will write:

List`1

I want it to write just:

List

How can I do that? Is there a smarter way to do it without having to use Substring or similar string manipulation functions?

6 Answers
static void Main(string[] args)
{

    Console.WriteLine(WhatIsMyType<IEnumerable<string>>());
    Console.WriteLine(WhatIsMyType<List<int>>());
    Console.WriteLine(WhatIsMyType<IList<int>>());
    Console.WriteLine(WhatIsMyType<List<ContentBlob>>());
    Console.WriteLine(WhatIsMyType<int[]>());
    Console.WriteLine(WhatIsMyType<ContentBlob>());
    Console.WriteLine(WhatIsMyType<Dictionary<string, Dictionary<int, int>>>());
}

public static string WhatIsMyType<T>()
{
    return typeof(T).NameWithGenerics();
}

public static string NameWithGenerics(this Type type)
{
    if (type == null)
        throw new ArgumentNullException(nameof(type));

    if (type.IsArray)
        return $"{type.GetElementType()?.Name}[]";

    if (!type.IsGenericType) 
        return type.Name;

    var name = type.GetGenericTypeDefinition().Name;
    var index = name.IndexOf('`');
    var newName = index == -1 ? name : name.Substring(0, index);
        
    var list = type.GetGenericArguments().Select(NameWithGenerics).ToList();
    return $"{newName}<{string.Join(",", list)}>";
}

Example output:

IEnumerable<String>
List<Int32>
IList<Int32>
List<ContentBlob>
Int32[]
ContentBlob
Dictionary<String,Dictionary<Int32,Int32>>

Here's the code from this answer inside a static class and namespace for easier copy-and-pasting.

Also, there's another extension method to get the type its namespace.

using System;

namespace TODO
{
    public static class TypeExtensions
    {
        /// <summary>
        /// From: https://stackoverflow.com/a/6386234/569302
        /// </summary>
        public static string GetNameWithoutGenericArity(this Type t)
        {
            string name = t.Name;
            int index = name.IndexOf('`');
            return index == -1 ? name : name.Substring(0, index);
        }
        public static string GetFullNameWithoutGenericArity(this Type t)
        {
            var result = $"{t.Namespace}.{t.GetNameWithoutGenericArity()}";
            return result;
        }
    }
}

The easiest way I can think of as of C#6(I think) you can do the following:

public static void Main(string[] args)
{
    Console.WriteLine(nameof(List<int>));
    Console.WriteLine(nameof(Dictionary<int, int>));
}

This will print:

List
Dictionary
Related