20

我最近需要为任意类型构建 C# 特定名称(必须始终包含 global:: 说明符)并且遇到以下问题:

// 1 - value: System.String[,,,][,,][,]
string unexpectedFullName = typeof( string[,][,,][,,,] ).FullName;      

// 2 - value: System.String[,][,,][,,,]
string expectedFullName = Type.GetType( "System.String[,][,,][,,,]" ).FullName;

我期望在这两种情况下返回的值是相同的。但是,由于某种原因,值的与数组相关的部分似乎被颠倒了(案例 1)。这是逆转预期的行为吗?

4

2 回答 2

13

虽然返回的值Type.FullName和 C# 类型标识符有时碰巧是相同的,但这并不能保证。请记住,Type.FullName无论从什么 CLI 语言调用它,无论是 C#、VB.NET、Oxygene 还是其他任何语言,它都会返回相同的值。

对于多维和锯齿状数组,C# 语法按照它们稍后编写的顺序列出索引,而反射语法返回与数组逻辑结构匹配的内容。并且a(C#)string[,][,,][,,,]毕竟是类型的值string,其为4维数组(即string[,,,]),其为3维数组(即string[,,,][,,])且其为二维数组(即string[,,,][,,][,])。

FullName您可能希望Type在分析类型时检查类的属性,而不是依赖于返回的反射语法名称。可以从那里检索诸如维数通用参数之类的信息。

在构造类型时,您还可以使用MakeArrayType或等方法MakeGenericType在运行时创建复杂类型,而无需构造包含新类型成分的字符串。

Marc Gravell指出了这个答案的一些内容- 谢谢!

于 2012-07-30T12:50:34.447 回答
2

注意:这并不能直接解决您的问题

这是逆转预期的行为吗?

但我觉得它增加了它。


您可以使用GenerateCodeFromExpression返回一个字符串,该字符串可用于生成为您生成类型的代码,例如使用此代码(由hvd从此SO 答案修改):

/// <summary>
/// <para>Returns a readable name for this type.</para>
/// <para>e.g. for type = typeof(IEnumerable&lt;IComparable&lt;int&gt;&gt;),</para>
/// <para>type.FriendlyName() returns System.Collections.Generic.IEnumerable&lt;System.IComparable&lt;int&gt;&gt;</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;
}

通过让codeDomProvider处理字符串表示,您可以确保生成的内容与您定义类型的方式相匹配。

结果FullName

// 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();
于 2015-03-09T13:27:46.247 回答