我最近需要为任意类型构建C#特定名称(必须始终包含global :: specifier)并且遇到以下问题:
// 1 - value: System.String[,,,][,,][,]
string unexpectedFullName = typeof( string[,][,,][,,,] ).FullName;
// 2 - value: System.String[,][,,][,,,]
string expectedFullName = Type.GetType( "System.String[,][,,][,,,]" ).FullName;
我原以为在这两种情况下返回的值都是相同的。但是,由于某种原因,数组相关部分的值似乎是相反的(案例1)。这是逆转的预期行为吗?
答案 0 :(得分:13)
虽然Type.FullName
返回的值和C#类型标识符有时恰好相同,但不保证这一点。请记住,Type.FullName
返回相同的值,无论它是从哪个CLI语言调用,无论是C#,VB.NET,Oxygene还是其他任何东西。
对于多维和锯齿状数组,C#语法按照稍后编写的顺序列出索引,而反射语法返回与数组逻辑结构匹配的内容。毕竟,(C#)string[,][,,][,,,]
是string
类型的值,它是一个4维数组(即string[,,,]
),它是一个三维数组(即{{ 1}})及其二维数组(即string[,,,][,,]
)。
您可能希望在分析类型时检查string[,,,][,,][,]
类的属性,而不是依赖FullName
返回的反射语法名称。可以从那里检索number of dimensions或generic arguments等信息。
构造类型时,您还可以使用MakeArrayType
或MakeGenericType
等方法在运行时创建复杂类型,而无需构建包含新类型成分的字符串。
Marc Gravell指出了这个答案的一些内容 - 谢谢!
答案 1 :(得分:2)
注意:这并不能直接解决您的问题
这种逆转是预期的行为吗?
但我觉得它添加。
您可以使用GenerateCodeFromExpression
返回一个字符串,该字符串可用于生成代码以便为您生成类型,例如使用此代码(由this SO answer hvd修改后的codeDomProvider
) :
/// <summary>
/// <para>Returns a readable name for this type.</para>
/// <para>e.g. for type = typeof(IEnumerable<IComparable<int>>),</para>
/// <para>type.FriendlyName() returns System.Collections.Generic.IEnumerable<System.IComparable<int>></para>
/// <para>type.Name returns IEnumerable`1</para>
/// <para>type.FullName() returns System.Collections.Generic.IEnumerable`1[[System.IComparable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]</para>
/// </summary>
public static string FriendlyName(this Type type)
{
string result;
using ( var codeDomProvider = CodeDomProvider.CreateProvider("C#") )
{
var typeReferenceExpression = new CodeTypeReferenceExpression(new CodeTypeReference(type));
using ( var writer = new StringWriter() )
{
codeDomProvider.GenerateCodeFromExpression(typeReferenceExpression, writer, new CodeGeneratorOptions());
result = writer.GetStringBuilder().ToString();
}
}
return result;
}
通过让FullName
处理字符串表示,您可以确定生成的内容将与您定义类型的方式相匹配。
结果{{3}}:
// returns "System.String[,,,][,,][,]"
typeof(string[,][, ,][, , ,]).FullName;
// returns "System.String[,][,,][,,,]"
typeof(string[, , ,][, ,][,]).FullName;
// returns "System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
typeof(List<int>).FullName;
FriendlyName
// returns "string[,][,,][,,,]"
typeof(string[,][, ,][, , ,]).FriendlyName();
// returns "string[,,,][,,][,]"
typeof(string[, , ,][, ,][,]).FriendlyName();
// returns "System.Collections.Generic.List<int>"
typeof(List<int>).FriendlyName();