Как мне получить имя типа аргумента универсального типа?

102

Если у меня есть подпись метода, например

public string myMethod<T>( ... )

Как я могу внутри метода получить имя типа, которое было задано как аргумент типа? Я бы хотел сделать что-то подобное typeof(T).FullName, но это действительно работает ...

Томас Ашан
источник
10
typeof(T).FullName должно работать. Что происходит вместо этого?
Натан Тейлор
Я получил ошибки компилятора в этом утверждении - но, очевидно, они были вызваны чем-то другим, потому что теперь он работает. Благодарность!
Томас Ашан

Ответы:

164

Ваш код должен работать. typeof(T).FullNameсовершенно верно. Это полностью компилируемая, работающая программа:

using System;

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

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

        Console.ReadKey();
    }

}

Выполнение вышеприведенных отпечатков (как и ожидалось):

System.Int32
Рид Копси
источник
Обязательно протестируйте его с помощью MyMethod <int>> () и посмотрите, что вы получите ... вы должны учитывать типы, допускающие значение NULL, если вы заботитесь о базовом типе в этом сценарии.
GR7
1
Вы имеете в виду " <int?>" Если так, то это работает, но вы получаете System.Nullable<int>(в синтаксисе полного имени), что и следовало ожидать ...
Рид Копси,
Несмотря на то, что у меня уже было решение (хотя оно по какой-то причине не сработало ...), я дам вам очки репутации за написание лучшего ответа на данный момент =)
Томас Ашан
1
Это как раз помог мне , так как я предполагал , что nameof(T)и typeof(T).Nameбудет делать то же самое. Оказывается, nameof(T)просто возвращается T.
dahvyd
7

typeof(T).Nameи typeof(T).FullNameработают на меня. Я получаю тип, переданный в качестве аргумента.

GR7
источник
1
ах. Если переданный вами тип имеет значение Nullable, чтобы получить базовый тип, вам придется использовать что-то вроде typeof (T) .GetGenericArguments () [0]
GR7
чтобы проверить, имеет ли тип значение NULL, вы должны использовать typeof (T) .IsGenericType, а если это так, вы должны использовать следующее, чтобы получить Name или FUllName ((Type) typeof (T) .GetGenericArguments () [0 ]). Имя
GR7
1

Предполагая, что у вас есть доступный экземпляр T, он ничем не отличается от любого другого типа.

var t = new T();

var name = t.GetType().FullName;
мать
источник
2
Вам даже не нужен экземпляр T .... typeof (T) отлично работает без экземпляра ... Ваш будет давать другое поведение, если подкласс передается в метод (в качестве аргумента) ..
Рид Копси
1
Проблема с этим кодом в том, что если у T нет конструктора без параметров, он не будет работать.
Натан Тейлор
@Nathan - это был просто пример, демонстрирующий получение экземпляра T. Предположительно, в общем методе у него будет доступен некоторый тип T. @ Рид - ты, конечно, прав, я предполагал, что это именно то, что ему нужно.
womp
Другая проблема может возникнуть в случае, если T является абстрактным классом или интерфейсом - приведенный выше код не будет работать. В случае наличия ограничения универсального типа («где») этот тип кода может быть безопасным, поскольку мы знаем конструктор и на самом деле могут иметь причины для создания экземпляра типа. В остальном создание экземпляра расточительно.
Эндрю