173

If I have a method signature like

public string myMethod<T>( ... )

How can I, inside the method, get the name of the type that was given as type argument? I'd like to do something similar to typeof(T).FullName, but that actually works...

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402

6 Answers6

261

Your code should work. typeof(T).FullName is perfectly valid. This is a fully compiling, functioning program:

using System;

class Program 
{
    public static string MyMethod<T>()
    {
        return typeof(T).FullName;
    }

    static void Main(string[] args)
    {
        Console.WriteLine(MyMethod<int>());

        Console.ReadKey();
    }

}

Running the above prints (as expected):

System.Int32
cja
  • 9,512
  • 21
  • 75
  • 129
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Make sure to test it with MyMethod>() and see what you get...you have to account for nullable types if you care for the underlying type in that scenario. – GR7 Apr 05 '10 at 23:11
  • 1
    You mean "``" If so, it works, but you get `System.Nullable` (in full name syntax), which is what you'd expect... – Reed Copsey Apr 05 '10 at 23:15
  • Even though I already had the solution (although it didn't work for some reason...), I'll give you the rep points for writing the best answer by far =) – Tomas Aschan Apr 05 '10 at 23:49
  • 7
    This just helped me since I assumed that `nameof(T)` and `typeof(T).Name` would do the same thing. Turns out `nameof(T)` just returns `T`. – dahvyd Jan 08 '20 at 06:08
21

This extension method outputs the simple type name for non-generic types, and appends the list of generic arguments for generic types. This works fine for scenarios where you don't need to worry about inner generic arguments, like IDictionary<int, IDictionary<int, string>>.

using System;
using System.Linq;

namespace Extensions
{ 
    public static class TypeExtensions
    {
        /// <summary>
        /// Returns the type name. If this is a generic type, appends
        /// the list of generic type arguments between angle brackets.
        /// (Does not account for embedded / inner generic arguments.)
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>System.String.</returns>
        public static string GetFormattedName(this Type type)
        {
            if(type.IsGenericType)
            {
                string genericArguments = type.GetGenericArguments()
                                    .Select(x => x.Name)
                                    .Aggregate((x1, x2) => $"{x1}, {x2}");
                return $"{type.Name.Substring(0, type.Name.IndexOf("`"))}"
                     + $"<{genericArguments}>";
            }
            return type.Name;
        }
    }
}
Paul Smith
  • 3,104
  • 1
  • 32
  • 45
17

typeof(T).Name and typeof(T).FullName are working for me. I get the type passed as an argument.

d219
  • 2,707
  • 5
  • 31
  • 36
GR7
  • 5,083
  • 8
  • 48
  • 66
  • 3
    ah. If the type you passed is Nullable, to get the underlying type you'd have to use something like typeof (T).GetGenericArguments()[0] – GR7 Apr 05 '10 at 22:55
  • 2
    to check if the type if nullable, you'd use typeof(T).IsGenericType, and if it is, you'd use the following to get the Name or FUllName ((Type)typeof(T).GetGenericArguments()[0]).Name – GR7 Apr 05 '10 at 22:58
6

Your code should work. You can also get the name of the class instead of the full name including namespace, for example:

using System;

namespace ConsoleApp1
{
    class Program
    {
        public static string GettingName<T>() => typeof(T).Name;

        public static string GettingFullName<T>() => typeof(T).FullName;

        static void Main(string[] args)
        {
            Console.WriteLine($"Name: {GettingName<decimal>()}");
            Console.WriteLine($"FullName: {GettingFullName<decimal>()}");
        }
    }
}

Output of running above program is:

Name: Decimal
FullName: System.Decimal

Here's a dotnet fiddle of the above code you can try out

Jim Aho
  • 9,932
  • 15
  • 56
  • 87
2

Assuming you have some instance of a T available, it's no different than any other type.

var t = new T();

var name = t.GetType().FullName;
womp
  • 115,835
  • 26
  • 236
  • 269
  • 3
    You don't even need an instance of T.... typeof(T) works fine with no instance... Yours will give a different behavior if a subclass is passed into the method (as an argument).. – Reed Copsey Apr 05 '10 at 22:52
  • 1
    The problem with that code is that if T does not have a parameterless constructor then it will not work. – Nathan Taylor Apr 05 '10 at 22:53
  • @Nathan - it was just an example to show getting an instance of T. Presumably on a generic method he'll have some T type available. @Reed - you're correct of course, I assumed that was what he was after. – womp Apr 05 '10 at 23:13
  • Another issue would be in the case that T is an abstract class or an interface - the above code would not work. In the case that there is a generic type constraint (the "where") then this type of code can be safe since we know the constructor and may actually have reasons to instantiate the type. Other than that instantiation is wasteful. – Andrew Sep 20 '15 at 10:25
0
private static string ExpandTypeName(Type t) =>
    !t.IsGenericType || t.IsGenericTypeDefinition
    ? !t.IsGenericTypeDefinition ? t.Name : t.Name.Remove(t.Name.IndexOf('`'))
    : $"{ExpandTypeName(t.GetGenericTypeDefinition())}<{string.Join(',', t.GetGenericArguments().Select(x => ExpandTypeName(x)))}>";
Peter Morris
  • 20,174
  • 9
  • 81
  • 146