Click here to Skip to main content
12,294,696 members (67,237 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

17.5K views
188 downloads
19 bookmarked
Posted

User-friendly names for Types

, 26 Jan 2015 CPOL
Rate this:
Please Sign up or sign in to vote.
How to display a Type name in a user-friendly format.

Introduction

The Name property of the Type class provides us with a name that most of the time does not correspond with what we type in code. For instance, a List<string> is really a List`1[String] (without the namespaces). This article provides an extension method that generates a user-friendly name for any given Type. It uses recursion to handle any name step-by-step. It will for instance take the type Tuple<string, double> and recursively find Tuple, double, and string and actually return 'Tuple<string, double>' and not 'Tuple`2[String, Double]'.

Using the code

The method, dubbed FriendlyName, allows four options to tweak the output:

  • useKeywords -- Indicates whether Types that are represented in C# by keywords should be written as such. E.g., int instead of Int32.
  • showGenericArguments -- Applies only to Generic Type Definitions (List<> and such). Indicates whether their Type parameters should be included. E.g., List<T> instead of just List<>. If true, the keywords 'in' and 'out' indicating variance will also be included. E.g., IEnumerable<out T>.
  • showDeclaringType -- Applies to nested types. Indicates whether they should be preceded by their declaring Type. E.g., MyType.NestedType instead of just NestedType.
  • compactNullable -- Indicates whether Nullable types should be written with a '?'. E.g., int? instead of Nullable<int>.

Different types of Types

Some notes on different 'types' of Types and how they are handled:

Generic Types

Generic Types have a name that ends in a back-tick and a number indicating how many Type parameters it contains. These are stripped because they are not really part of the name. (We want List, not List`1.)

Anonymous Types

Anonymous Types are implemented as generic types, so they also have a name that ends in a back-tick and a number. These are stripped, but the rest of the name is left intact. They have rather ugly names, like <>f__AnonymousType0<string, int> but that is by design, so nothing can be done to make their names more readable.

Pointers and Arrays

Pointers have a name that ends in '*'. Pointers need special handling because their element Type might be a 'special' type as well. A long* for instance is not recognized as a 'keyword type'. Depending on parameters, it must be displayed as either long* or Int64*. This is done recursively: first the long type is processed and then the '*' is added. The same goes for arrays.

Unhandled problems

The C# Type system is a complex thing. This creates some problems for FriendlyName that are not handled:

Jagged arrays

Jagged arrays are reversed. We type char[][,], but the actual type is char[,][]

Generic Types

Nested Generic Types in particular are tricky. If we take Dictionary<string, double>.Enumerator for instance, the actual type is Dictionary<TKey, TValue>.Enumerator<string, double>!

Example of use

var c = Enumerable.Repeat(0, 1).GetEnumerator();
var person = new { Name = "Someone", Age = 30 };
int? i = 1;
var tuple = Tuple.Create("", i, 
     new List<Dictionary<string, char[,]>>(), person);

Type[] types =
{
    c.GetType(),
    typeof(IEnumerable<>),
    typeof(char[][,,]),
    tuple.GetType(),
    typeof(Func<int, string, int?, List<string>>),
    typeof(Func<int, string, int?, List<string>>).GetGenericTypeDefinition(),
    typeof(Dictionary<string, double>.Enumerator),
    typeof(Nullable<>)
};

foreach (Type type in types) {
    Console.WriteLine(type.FriendlyName());
    Console.WriteLine(type.FriendlyName(useKeywords: false, showGenericArguments: false, compactNullable: false));
}

//Output:
//
//Enumerable.<RepeatIterator>d__bc<int>
//Enumerable.<RepeatIterator>d__bc<Int32>
//IEnumerable<out T>
//IEnumerable<>
//char[,,][]
//Char[,,][]
//Tuple<string, int?, List<Dictionary<string, char[,]>>, <>f__AnonymousType0<string, int>>
//Tuple<String, Nullable<Int32>, List<Dictionary<String, Char[,]>>, <>f__AnonymousType0<String, Int32>>
//Func<int, string, int?, List<string>>
//Func<Int32, String, Nullable<Int32>, List<String>>
//Func<in T1, in T2, in T3, out TResult>
//Func<,,,>
//Dictionary<TKey, TValue>.Enumerator<string, double>
//Dictionary<,>.Enumerator<String, Double>
//T?
//Nullable<>

 

History

  • July 16th, 2013 -- First posting.
  • January 26th, 2015 -- Fixed a bug and updated text of the article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dennis_E
Software Developer (Junior)
Netherlands Netherlands
Software developer with a bachelor degree and a few years experience (studied computer science at a university as well, but didn't finish). Really love C#, but work usually involves Java. Some experience with VB and C as well.

When hobbying I almost exclusively use C# and AutoHotkey. In a previous life I did some Haskell and Modula-3 and similar stuff. I enjoy games and solving puzzles like on http://projecteuler.net/ (I think I'm stuck at level 4, though)

You may also be interested in...

Comments and Discussions

 
GeneralWhere to use this code? Pin
Member 1140565027-Jan-15 1:57
memberMember 1140565027-Jan-15 1:57 
QuestionBUG! Pin
Jens-Madsen19-Jan-15 14:39
memberJens-Madsen19-Jan-15 14:39 
AnswerRe: BUG! Pin
Dennis_E25-Jan-15 22:05
professionalDennis_E25-Jan-15 22:05 
GeneralAwesome Pin
lookitstony25-Jul-14 5:04
memberlookitstony25-Jul-14 5:04 
GeneralMy vote of 4 Pin
Amir Mohammad Nasrollahi14-Aug-13 23:41
professionalAmir Mohammad Nasrollahi14-Aug-13 23:41 
GeneralMy vote of 5 Pin
Paulo Zemek14-Aug-13 11:36
memberPaulo Zemek14-Aug-13 11:36 
GeneralMy vote of 5 Pin
VitorHugoGarcia17-Jul-13 4:09
memberVitorHugoGarcia17-Jul-13 4:09 
GeneralRe: My vote of 5 Pin
Grimlock17-Jul-13 22:28
memberGrimlock17-Jul-13 22:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160525.2 | Last Updated 26 Jan 2015
Article Copyright 2013 by Dennis_E
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid