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.FullNameC#、VB.NET、Oxygene など、呼び出し元の CLI 言語に関係なく、同じ値を返すことに注意してください。

多次元配列とジャグ配列の場合、C# 構文は後で記述される順序でインデックスを一覧表示しますが、リフレクション構文は配列の論理構造に一致するものを返します。そして、(C#)string[,][,,][,,,]は結局、 type の値でありstring、その 4 次元配列 (すなわちstring[,,,])、その 3 次元配列 (すなわちstring[,,,][,,])、およびその 2 次元配列 (すなわち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文字列表現を処理させることで、生成されたものが Type の定義方法と一致することを確認できます。

の結果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 に答える