Linqの.Select()を使用するとIEnumerableが返されるのはなぜですかタイプが明確に定義されていても?

casting dapper dynamic linq

質問

私はDapperを使って動的オブジェクトを返し、時にはそれらを手動でマッピングしています。すべてうまくいっていますが、キャスティングの法則と、次の例が真実である理由が不思議でした。

(これらの例では、私は「StringBuilder」を既知の型として使用しましたが、通常は「Product」のようなものです)

例1:なぜ、 'makeStringBuilder'がStringBuilderオブジェクトを明確に返すとしても、これはIEnumerable<dynamic>返しますか?

Example2: IEnumerable<StringBuilder>場合、これはなぜビルドされますが、 'Example1'は作成されませんか?

例3:例2と同じ質問?

private void test()
    {
        List<dynamic> dynamicObjects = {Some list of dynamic objects};

        IEnumerable<dynamic> example1 = dynamicObjects.Select(s => makeStringBuilder(s));

        IEnumerable<StringBuilder> example2 = dynamicObjects.Select(s => (StringBuilder)makeStringBuilder(s));

        IEnumerable<StringBuilder> example3 = dynamicObjects.Select(s => makeStringBuilder(s)).Cast<StringBuilder>();

    }

    private StringBuilder makeStringBuilder(dynamic s)
    {
        return new StringBuilder(s);
    }

上の例では、これを処理するための推奨方法はありますか?この怪我のようにキャストしていますか?ありがとう!

受け入れられた回答

dynamicでも、パラメータとして使用dynamic場合でも、式全体が動的バインディングによって処理され、コンパイル時に(その実行時の型に基づいているため)「動的」になります。これはC#仕様の7.2.2でカバーされています:

しかし、式が動的式である場合(つまり、型が動的である場合)、これは、それが関与するバインディングは実行時の型(つまり、実行時に示すオブジェクトの実際の型)に基づいている必要があることを示します。コンパイル時に持っている型よりも。したがって、このような操作のバインディングは、プログラムの実行中に操作が実行される時間まで延期されます。これは動的バインディングと呼ばれます。

あなたの場合、キャストを使用すると安全にIEnumerable<StringBuilder>に変換され、パフォーマンスにはほとんど影響しません。 example2バージョンは、非常にわずかよりも効率的であるexample3バージョンが、この方法で使用する場合の両方が非常にわずかなオーバーヘッドを持っています。


人気のある回答

私が "なぜ"をよく話すことはできませんが、私はexample1を次のように書くことができるはずだと思います。

IEnumerable<StringBuilder> example1 = dynamicObjects.Select<dynamic, StringBuilder>(s => makeStringBuilder(s));

コンパイラにどのような型を取るべきかをコンパイラに伝える必要がありますが、他の人が正しい型を推論できない理由を明確にすることができます。しかし、投影タイプを指定することで、実際にキャストする必要がなくなり、パフォーマンス上のメリットが得られるはずです。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow