17

リフレクションで遊んでみましたが、次のような状況に遭遇しました。

IEnumerable<>次のコードでは、「obj」の型がorICollection<>またはであると仮定しましょうIList<>

コレクションを列挙し、リフレクションを使用して個々のアイテムを書きたいように、この System.Object をIEnumerable<>常に (とにかく継承しICollection<>て) キャストしたいと思います。IList<>IEnumerable<>

この背後にある動機は、シリアライザーが一般的にデータをシリアル化する方法を確認しようとしているだけなので、リフレクションも理解できるようにその状況をシミュレートしようとしています。

オブジェクトを非ジェネリック IEnumerableにキャストすることを考えましたが、実際のインスタンスを言うと、オブジェクトの不要なボックス化が発生すると思いましたIEnumerable<int>...私は正しいと思いますか?

private void WriteGenericCollection(object obj)
    {
        Type innerType = obj.GetType().GetGenericArguments()[0];

        //Example: IEnumerable<int> or IEnumerable<Customer>
        Type generatedType = typeof(IEnumerable<>).MakeGenericType(innerType);

        //how could i enumerate over the individual items?
    }
4

2 に答える 2

24

アイテムの実際の型は実行時までわからないため、ジェネリックIEnumerable<T>インターフェイスを使用する必要はありません。非ジェネリックなものを使用するだけですIEnumerable(ジェネリックなものはそれから継承されます):

private void WriteGenericCollection(object obj)
{
    IEnumerable enumerable = (IEnumerable)obj;
    foreach(object item in enumerable)
    {
        ...
    }
}
于 2012-08-29T00:19:33.773 に答える
4

あなたの質問は誤解に満ちています。それらを片付けましょう。

IEnumerable<>次のコードでは、「obj」の型がorICollection<>またはであると仮定しましょう IList<>

それが真で、列挙可能な型がわかっている場合、メソッドを記述するより良い方法は次のようになります。

private void WriteGenericCollection<T>(IEnumerable<T> obj)
{
    // ...
}

この System.Object を常に IEnumerable<> にダウンキャストしたい (ICollection<> と IList<> はとにかく IEnumerable<> から継承するため)、コレクションを列挙し、リフレクションを使用して個々の項目を書きたいと思います。

インターフェイスについて話すとき、「継承」という用語は正しくありません。また、間違った考えを与える可能性もあります。インターフェースはコントラクトと考えるのが一番です: インターフェースの実装を検討するときは、作成者が意図したとおりに実装するか、まったく実装しないかを決めるしかありません。

一部のインターフェイスは、他のインターフェイスのスーパーセットです。彼らの契約には、「実装者は、契約に記載されている他のことに加えて、これを行う必要がある」と書かれています。ただし、インターフェースには実装がないため、継承で一般的な実装の共有はありません。

「ダウンキャスト」も、そのメソッドで行っていることを表す正しい用語ではありません。ダウンキャストとは、より派生したクラスにキャストすることを意味します。インターフェースへのキャストもあります:

// Note: the method is still generic!
private void WriteGenericCollection<T>(object obj)
{
    var casted = (IEnumerable<T>)obj;
}

オブジェクトを非ジェネリック IEnumerable にダウンキャストすることを考えましたが、IEnumerable の実際のインスタンスを例に挙げると、オブジェクトの不要なボックス化が発生すると考えました...私は正しいと思いますか?

ボックス化は、オブジェクトが値(数値型、 a 、 anまたは a ) である場合にのみ発生します。オブジェクトがいくつかの既知のものを実装している場合は、単純にそれにキャストできます。が不明な場合は、非ジェネリックにキャストし、パフォーマンス ヒットの可能性を考慮します (いずれの場合も回避方法はありません)。IEnumerable<T>TboolenumstructIEnumerable<T>TTIEnumerable

オブジェクトについて何も知らない場合にのみ、リフレクションを使用する必要があります (その場合はもちろん、列挙できないオブジェクトについても計画を立てる必要があります。そうしないと、そもそもオブジェクトをメソッドに渡すことを許可する必要はありません)。

于 2012-08-29T00:18:36.947 に答える