Получить имя типа без полного пространства имен

293

У меня есть следующий код:

return "[Inserted new " + typeof(T).ToString() + "]";

Но

 typeof(T).ToString()

возвращает полное имя, включая пространство имен

В любом случае можно просто получить имя класса (без квалификаторов пространства имен?)

Лиора
источник
7
Кстати, письмо string1 + anything.ToString() + string2излишне. Компилятор вставляет вызов ToStringавтоматически, если вы делаете string1 + anything + string2.
Тим Робинсон
13
не звучит грубо, но, если бы вы проверили, какие свойства доступны в Typeэкземпляре (как возвращено typeof(..)), я уверен, что вы сами это выясните ...
Питер Лиллевольд

Ответы:

530
typeof(T).Name // class name, no namespace
typeof(T).FullName // namespace and class name
typeof(T).Namespace // namespace, no class name
Тим Робинсон
источник
5
Nameне учитывает параметры типа.
gregsdennis
73
Или this.GetType().Name, this.GetType().FullNameи т. Д., Если иметь дело с примерами.
Авенмор
1
Nameтакже не учитывает вложенные типы!
Воинственный шимпанзе
33

Попробуйте это, чтобы получить параметры типа для универсальных типов:

public static string CSharpName(this Type type)
{
    var sb = new StringBuilder();
    var name = type.Name;
    if (!type.IsGenericType) return name;
    sb.Append(name.Substring(0, name.IndexOf('`')));
    sb.Append("<");
    sb.Append(string.Join(", ", type.GetGenericArguments()
                                    .Select(t => t.CSharpName())));
    sb.Append(">");
    return sb.ToString();
}

Возможно, не лучшее решение (из-за рекурсии), но оно работает. Выходы выглядят так:

Dictionary<String, Object>
gregsdennis
источник
3
Это должен быть принятый ответ, поскольку он должным образом учитывает общие типы, которые могут повторяться (например, Dictionary <int?, Int?>).
Отис
+1 за концепцию. Но не нравится неудачная преждевременная оптимизация. Он создает новый StringBuilder в каждом рекурсивном вызове (даже в базовом случае, когда он не используется), но игнорирует string.Joinвременную и LINQ-лямбду. Просто используйте, Stringпока не узнаете, что это узкое место. / rant
Найджел Тач
1
Найджел, тут же написано, что это, вероятно, не лучшее решение :)
gregsdennis
ShortName - более короткое имя :)
Валера
5

После C # 6.0 (включая) вы можете использовать nameof expression:

using Stuff = Some.Cool.Functionality  
class C {  
    static int Method1 (string x, int y) {}  
    static int Method1 (string x, string y) {}  
    int Method2 (int z) {}  
    string f<T>() => nameof(T);  
}  

var c = new C()  

nameof(C) -> "C"  
nameof(C.Method1) -> "Method1"   
nameof(C.Method2) -> "Method2"  
nameof(c.Method1) -> "Method1"   
nameof(c.Method2) -> "Method2"  
nameof(z) -> "z" // inside of Method2 ok, inside Method1 is a compiler error  
nameof(Stuff) = "Stuff"  
nameof(T) -> "T" // works inside of method but not in attributes on the method  
nameof(f) -> f  
nameof(f<T>) -> syntax error  
nameof(f<>) -> syntax error  
nameof(Method2()) -> error This expression does not have a name  

Заметка! nameofне получить базовый тип времени выполнения объекта, это просто аргумент времени компиляции. Если метод принимает IEnumerable, nameof просто возвращает «IEnumerable», тогда как фактическим объектом может быть «List».

Стас Бояринцев
источник
3
nameofне возвращает имяType
Найджел Touch Touch
@NigelTouch Я проверил и nameofвернул имя Type, скриншот с доказательством: prntscr.com/irfk2c
Стас Бояринцев
1
Извините, я не очень хорошо объяснил. Я имею в виду, что он не получает время выполнения базового объекта Type, это просто аргумент времени компиляции. Если метод принимает, IEnumerableто nameofпросто возвращает «IEnumerable», тогда как фактическим объектом может быть «List <string>». Не думаю, что это отвечает на вопрос ОП.
Найджел
-2

лучший способ использовать:

obj.GetType().BaseType.Name
Хоссейн Эбрахими
источник
1
Пожалуйста, дайте некоторое объяснение вашему ответу, чтобы сделать его более понятным для других пользователей.
Станислав Мехоношин
Однажды я обнаружил, что «GetType (). Имя» просто написано внутри виртуальной функции. Может кто-нибудь объяснить мне, почему он не имеет obj.GetType (). BaseType.Name? Я учусь. Я понимаю цель, но не все детали синтаксиса. Спасибо.
Диего Орельяна
При чем тут базовый тип?
Джонни 5
Мой тест obj.GetType().BaseType.Nameвозвращается, "TypeInfo"что не является желаемым решением, как я ожидаю.
Nasenbaer