[ACCEPTED]-Is there a way to get a type's alias through reflection?-reflection

Accepted answer
Score: 60

Nope - just create a Dictionary<Type,string> to map all of the 2 types to their aliases. It's a fixed set, so 1 it's not hard to do:

private static readonly Dictionary<Type, string> Aliases =
    new Dictionary<Type, string>()
{
    { typeof(byte), "byte" },
    { typeof(sbyte), "sbyte" },
    { typeof(short), "short" },
    { typeof(ushort), "ushort" },
    { typeof(int), "int" },
    { typeof(uint), "uint" },
    { typeof(long), "long" },
    { typeof(ulong), "ulong" },
    { typeof(float), "float" },
    { typeof(double), "double" },
    { typeof(decimal), "decimal" },
    { typeof(object), "object" },
    { typeof(bool), "bool" },
    { typeof(char), "char" },
    { typeof(string), "string" },
    { typeof(void), "void" }
};
Score: 31

This doesn't use reflection, strictly speaking, but 6 you can get to the type's alias by using 5 CodeDOM:

Type t = column.DataType;    // Int64

string typeName;
using (var provider = new CSharpCodeProvider())
{
    var typeRef = new CodeTypeReference(t);
    typeName = provider.GetTypeOutput(typeRef);
}

Console.WriteLine(typeName);    // long

(Having said that, I think that 4 the other answers suggesting that you just 3 use a mapping from CLR types to C# aliases 2 are probably the best way to go with this 1 one.)

Score: 12

In case someone needs the dictionary with 1 nullables:

private static readonly Dictionary<Type, string> Aliases = new Dictionary<Type, string>()
    {
        { typeof(byte), "byte" },
        { typeof(sbyte), "sbyte" },
        { typeof(short), "short" },
        { typeof(ushort), "ushort" },
        { typeof(int), "int" },
        { typeof(uint), "uint" },
        { typeof(long), "long" },
        { typeof(ulong), "ulong" },
        { typeof(float), "float" },
        { typeof(double), "double" },
        { typeof(decimal), "decimal" },
        { typeof(object), "object" },
        { typeof(bool), "bool" },
        { typeof(char), "char" },
        { typeof(string), "string" },
        { typeof(void), "void" },
        { typeof(Nullable<byte>), "byte?" },
        { typeof(Nullable<sbyte>), "sbyte?" },
        { typeof(Nullable<short>), "short?" },
        { typeof(Nullable<ushort>), "ushort?" },
        { typeof(Nullable<int>), "int?" },
        { typeof(Nullable<uint>), "uint?" },
        { typeof(Nullable<long>), "long?" },
        { typeof(Nullable<ulong>), "ulong?" },
        { typeof(Nullable<float>), "float?" },
        { typeof(Nullable<double>), "double?" },
        { typeof(Nullable<decimal>), "decimal?" },
        { typeof(Nullable<bool>), "bool?" },
        { typeof(Nullable<char>), "char?" }
    };
Score: 4

Based on the above 2 answers for using a 6 Dictionary, I've written 2 basic extension 5 methods that might help clean up the use 4 a bit. Including this class in your project 3 you will be able to use it simply by calling 2 the Alias() or AliasOrName() methods on 1 the type as shown below.

Example usage;

        // returns int
        string intAlias = typeof(Int32).Alias();
        // returns int
        string intAliasOrName = typeof(Int32).AliasOrName();
        // returns string.empty
        string dateTimeAlias = typeof(DateTime).Alias();
        // returns DateTime
        string dateTimeAliasOrName = typeof(DateTime).AliasOrName();

The implementation;

public static class TypeExtensions
{
    public static string Alias(this Type type)
    {
        return TypeAliases.ContainsKey(type) ?
            TypeAliases[type] : string.Empty;
    }

    public static string AliasOrName(this Type type)
    {
        return TypeAliases.ContainsKey(type) ?
            TypeAliases[type] : type.Name;
    }

    private static readonly Dictionary<Type, string> TypeAliases = new Dictionary<Type, string>
    {
        { typeof(byte), "byte" },
        { typeof(sbyte), "sbyte" },
        { typeof(short), "short" },
        { typeof(ushort), "ushort" },
        { typeof(int), "int" },
        { typeof(uint), "uint" },
        { typeof(long), "long" },
        { typeof(ulong), "ulong" },
        { typeof(float), "float" },
        { typeof(double), "double" },
        { typeof(decimal), "decimal" },
        { typeof(object), "object" },
        { typeof(bool), "bool" },
        { typeof(char), "char" },
        { typeof(string), "string" },
        { typeof(void), "void" },
        { typeof(byte?), "byte?" },
        { typeof(sbyte?), "sbyte?" },
        { typeof(short?), "short?" },
        { typeof(ushort?), "ushort?" },
        { typeof(int?), "int?" },
        { typeof(uint?), "uint?" },
        { typeof(long?), "long?" },
        { typeof(ulong?), "ulong?" },
        { typeof(float?), "float?" },
        { typeof(double?), "double?" },
        { typeof(decimal?), "decimal?" },
        { typeof(bool?), "bool?" },
        { typeof(char?), "char?" }
    };
}
Score: 4
public string GetAlias(Type t)
{
    string typeName = "";
    using (var provider = new CSharpCodeProvider())
    {
        var typeRef = new CodeTypeReference(t);
        typeName = provider.GetTypeOutput(typeRef);
    }
    return typeName;
}

0

Score: 2

Keep it simple:

var aliasDict = new Dictionary<Type, string>() {
    { typeof(int), "int" },
    { typeof(long), "long" },
    // etc
}

Type reflectedType;
string aliasedTypeName = aliasDict[reflectedType];

0

Score: 1

I don't think there is. The alias is completly 4 a compile time concept specific to the paticular 3 .NET language you use. Once you reflect 2 and view the type you will see the true 1 .NET type of the object.

Score: 1

The dictionary answers are flexible, but 22 we can do one better if we want basic types 21 only:

public static class TypeNameExtensions
{
    private static readonly string[] TypeAliases = {
        "void",     // 0
        null,       // 1 (any other type)
        "DBNull",   // 2
        "bool",     // 3
        "char",     // 4
        "sbyte",    // 5
        "byte",     // 6
        "short",    // 7
        "ushort",   // 8
        "int",      // 9
        "uint",     // 10
        "long",     // 11
        "ulong",    // 12
        "float",    // 13
        "double",   // 14
        "decimal",  // 15
        null,       // 16 (DateTime)
        null,       // 17 (-undefined- presumably TimeSpan in some pre-1.0 C# alpha)
        "string",   // 18
    };

If you don't need to support array 20 types:

    public static bool TryGetNameAlias(this Type t, out string alias)
        => (alias = TypeAliases[(int)Type.GetTypeCode(t)]) != null && !t.IsEnum;

Edit: If you need to support array types:

    public static bool TryGetNameAlias(this Type t, out string alias)
    {
        string arrayBrackets = null;
        while (t.IsArray)
        {
            arrayBrackets += "[" + new string(',', t.GetArrayRank() - 1) + "]";
            t = t.GetElementType();
        }
        alias = TypeAliases[(int)Type.GetTypeCode(t)];
        if (alias == null || t.IsEnum)
            return false;
        alias += arrayBrackets;
        return true;
    }
}

This 19 is based on the TypeCode enum:
https://docs.microsoft.com/en-us/dotnet/api/system.typecode?view=netstandard-1.3
which has been 18 around since .Net 1.1

Should be faster than 17 a dictionary since it jumps straight into 16 an array using the TypeCode as index.

The 15 only downside is that we would need an extra 14 check if we want to alias Object as object.


If you are 13 wondering why this enum exist, it's used to 12 facilitate performant implementation of 11 System.IConvertible - which also exposes the GetTypeCode() method:
https://docs.microsoft.com/en-us/dotnet/api/system.iconvertible.gettypecode?view=netstandard-1.3

So in essence 10 it could be seen as an implementation detail 9 that someone one the original C# dev team 8 decided to make public for one reason or 7 another all the way back in the v1.1 days. Perhaps 6 so that others could take advantage of it 5 if they too needed to implement performant 4 fiddling about with the built in types?

Either 3 way it has been part of the language since 2 its early beginnings, over 20 years now! :D


(Personally I have leveraged TypeCode to built a small library for generic numeric range checking and other numeric-specific metadata methods, e.g. performing arithmetic using compile-time unknown generic numeric types without the use of reflection or try-catch attempts.)


Edit: Updated to support array types (including nested and multi-dimensional). 1
Edit: Updated to properly handle enum types.

More Related questions