2

したがって、これは以前にSOで議論されましたが、なぜこれが発生するのかについての説明を見たことがないと思います。また、コードでリフレクションを使用しようとしている平均的な開発者にとって、これがどのように役立つかを知ることもできません。

したがって、このコードを確認してください。

var fields = typeof(Person).GetFields(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance);

List<int>オブジェクトにが含まれている場合は、Personリフレクション「Name」がに設定されているフィールドが返されます。List`1辞書がある場合は、になりますDictionary`2。表面的には、これは作業を困難にしているように見えますが、私は次のことを言うことはできません

foreach (var fieldInfo in fields.Where(fieldInfo => fieldInfo.FieldType == typeof(List<int>)))
{
     //Do something.
}

これが出てくる理由は、私が現在取り組んでいるプロジェクトで次のことを見つけたからです。

    //Initialize collections
    FieldInfo[] properties = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (FieldInfo f in properties)
    {
       if (f.FieldType.Name == "IList`1" && f.GetValue(obj) == null)
       {
             object value = Container.Resolve(f.FieldType);
             f.SetValue(obj, value);

       }
   }

それから団結のための構成で私はこの幸福を見る

<alias alias="IList`1" type="System.Collections.Generic.IList`1, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

私はこれが悪いことを知っていることを本当に知りませんか?それは...ですか?もちろん動作しますが、これで問題がない場合でも(これにより、疑わしいコードダーが消えます)、元の質問は残ります。ジェネリックに関するディメンション情報は、プログラマーとしてどのようなメリットがありますか?

4

2 に答える 2

3

プログラマーを支援することは確かにありません。CLIがそれを要求するので、それはそこにあります。同じ識別子名を持つが、型引数の数が異なるジェネリック型が一意の型名を持つことを保証するというさらなる理論的根拠があります。ECMA 335仕様からのいくつかの言い回し:

CLSルール43:ジェネリック型の名前は、上記で定義されたルールに従って、ネストされていない型で宣言された、またはネストされている場合は型に新しく導入された型パラメーターの数をエンコードする必要があります。[注:CLS(コンシューマー):このルールに違反するタイプをコンシューマーする必要はありません。CLS(エクステンダー):コンシューマーと同じです。ジェネリック型の定義をサポートすることを選択したエクステンダーは、外部から見える型についてはこの規則に従う必要があります。CLS(フレームワーク):このルールに違反するタイプを公開してはなりません。エンドノート]

セクションII.9でいくつかの説明があります:

ジェネリック型は、のように、名前とそれに続く<…>で区切られたジェネリックパラメーターのリストで構成されC<T>ます。2つ以上のジェネリック型は、同じスコープ内で同じ名前ではなく、異なる数のジェネリックパラメーターで定義する必要があります。ただし、ソース言語レベルでジェネリックアリティにこのようなオーバーロードを許可するために、CLSルール43は、ジェネリック型名を一意のCIL名にマップするように定義されています。この規則では、1つ以上の汎用パラメーターを持つタイプCのCLS準拠の名前には、形式の接尾辞を付ける必要があります`n。ここで、nは、Cが持つ汎用パラメーターの数を表す10進整数定数(先行ゼロなし)です。例:タイプC、、C<T>およびC<K,V>のCLS準拠の名前はC、C 1<T>, andC2<K,V>、 それぞれ。[注:すべての標準ライブラリタイプの名前はCLSに準拠しています。例:System.Collections.Generic.IEnumerable`1。エンドノート]

申し訳ありませんが、正しい方法で出てきませんでした。回答を投稿するときに逆引用符を付けるのは難しいです。正確性については、ECMAドキュメントをご覧ください。

于 2012-10-26T13:46:35.740 に答える
2

コンパイル時に既知の型を処理する場合は、のを処理する必要はないNameのでType、などの名前Thing`nは問題になりません。

私がこれを行うときのように、あなたの最初の例で何が起こっているのかわかりません:

class Person
{
    private List<int> intList;
}

この:

class Program
{
    static void Main(string[] args)
    {
        var fields = typeof(Person).GetFields(BindingFlags.DeclaredOnly 
                                            | BindingFlags.NonPublic 
                                            | BindingFlags.Instance);

        foreach (var fieldInfo in 
            fields.Where(fieldInfo => fieldInfo.FieldType == typeof(List<int>)))
        {
            Console.WriteLine(fieldInfo.ToString());

        }
    }
}

私は私が期待するもの、すなわち

System.Collections.Generic.List`1[System.Int32] intList

提供するコードサンプルでも、コンパイル時に型がわかっています。あなたが示したものよりも優れている

//Initialize collections
FieldInfo[] properties = type.GetFields(BindingFlags.DeclaredOnly 
                                      | BindingFlags.NonPublic 
                                      | BindingFlags.Instance);
foreach (FieldInfo f in properties)
{
   if(typeof(IList<int>).IsAssignableFrom(f.FieldType)
   && f.GetValue(obj) == null)
   {
         object value = Container.Resolve(f.FieldType);
         f.SetValue(obj, value);
   }
}

あなたはaが何であるかを知っIList<int>ています。IsAssignableFromまたは必要に応じて使用できます==

IsAssignableFrom(私がいつもそうしているように、混乱した場合は、これを覚えておいてください。これif (a is b)はと同じテストif (typeof(b).IsAssignableFrom(a.getType()))です。順序は入れ替わります。

于 2012-10-26T14:04:02.113 に答える