3

Dapper を使用して動的オブジェクトを返し、手動でマッピングすることもあります。すべてが正常に機能していますが、キャストの法則とは何か、次の例が当てはまる理由は何かと考えていました。

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

IEnumerable<dynamic>例 1: 'makeStringBuilder' は明らかにStringBuilderオブジェクトを返すのに、なぜこれはを返すのですか?

例 2: なぜこれはビルドされるのに、'Example1' はビルドされないのIEnumerable<StringBuilder>ですか?

例 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);
    }

上記の例では、これを処理するための推奨される方法はありますか? このようにキャストするとパフォーマンスが低下しますか? ありがとう!

4

2 に答える 2

2

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

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

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

于 2012-10-02T19:39:06.143 に答える
1

「なぜ」についてはうまく話せませんが、example1 は次のように書けるはずです。

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

プロジェクションがどのタイプを取るべきかをコンパイラに伝える必要がありますが、正しいタイプを推測できない理由を他の誰かが明確にできると確信しています。しかし、投影タイプを指定することで、実際にキャストする必要がなくなり、パフォーマンスが向上すると思います。

于 2012-10-02T20:00:14.760 に答える