If I write:
var type = typeof(List);
Console.WriteLine(type.Name);
It will write:
List`1
No, it doesn't, because the "generic-type-string" is part of the name of type.
If someone is interested, I created some extensionmethods for this problem that create a more "readable" string
it produces something like
List[string]
outer.inner[other.whatever]
IEnumerable[T0]
Dictionary[string:int]
Test here
public static class TypeEx
{
public static string GetTypeName(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!type.IsGenericType)
return type.GetNestedTypeName();
StringBuilder stringBuilder = new StringBuilder();
_buildClassNameRecursiv(type, stringBuilder);
return stringBuilder.ToString();
}
private static void _buildClassNameRecursiv(Type type, StringBuilder classNameBuilder, int genericParameterIndex = 0)
{
if (type.IsGenericParameter)
classNameBuilder.AppendFormat("T{0}", genericParameterIndex + 1);
else if (type.IsGenericType)
{
classNameBuilder.Append(GetNestedTypeName(type) + "[");
int subIndex = 0;
foreach (Type genericTypeArgument in type.GetGenericArguments())
{
if (subIndex > 0)
classNameBuilder.Append(":");
_buildClassNameRecursiv(genericTypeArgument, classNameBuilder, subIndex++);
}
classNameBuilder.Append("]");
}
else
classNameBuilder.Append(type.GetNestedTypeName());
}
public static string GetNestedTypeName(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!type.IsNested)
return type.Name;
StringBuilder nestedName = new StringBuilder();
while(type != null)
{
if(nestedName.Length>0)
nestedName.Insert(0,'.');
nestedName.Insert(0, _getTypeName(type));
type = type.DeclaringType;
}
return nestedName.ToString();
}
private static string _getTypeName(Type type)
{
return type.IsGenericType ? type.Name.Split('`')[0]: type.Name;
}
}
No, it makes perfect sense for it to include the generic arity in the name - because it's part of what makes the name unique (along with assembly and namespace, of course).
Put it this way: System.Nullable and System.Nullable<T> are very different types. It's not expected that you'd want to confuse the two... so if you want to lose information, you're going to have to work to do it. It's not very hard, of course, and can be put in a helper method:
public static string GetNameWithoutGenericArity(this Type t)
{
string name = t.Name;
int index = name.IndexOf('`');
return index == -1 ? name : name.Substring(0, index);
}
Then:
var type = typeof(List<string>);
Console.WriteLine(type.GetNameWithoutGenericArity());