4

2 つの方法があり、そのうちの 1 つは、usingステートメント内で LINQ を使用してデータを返します。クエリの実行が延期され、使用している変数が既に破棄されているため、クエリが何らかの例外をスローする可能性があるのだろうか?

class Foo
{
    void Bar()
    {
       var bazResult = Baz();
       //... use bazResult here...
    }

    IEnumerable<int> Baz()
    {
        using (var d = new SomeDisposableSource())
        {
            return d.Select(e => e.Id);
        }
    }

}

ところで、すでに何らかの形で尋ねられているに違いありませんが、明らかな候補が見つかりません。だから私をあまり激しく蹴らないでください:)

4

6 に答える 6

4

オブジェクトが破棄された場合、例外があると思います。このスレッドは非常に似ており、問題を処理するためのいくつかの方法を提供します。簡単な方法は、実行を強制することreturn d.Select(e => e.Id).ToList()ですが、それはあなたには適していないかもしれません

于 2011-05-24T16:32:52.557 に答える
2

はい、例外をスローできますが、「SomeDisposableSource」の実装に依存します。Dispose() を呼び出す前にソースに IEnumerable または Array を取得するように要求していますが、実際には Dispose の後に各要素を列挙しているため、例外がスローされるかどうかは、その「yeld-return」の実際のコードに依存します。コード。(破棄されたオブジェクトを使用しますか?)

次のようにして、(より高いメモリ使用量で) 回避できます。

return d.Select(e => e.Id).ToArray();

そうすれば、Dispose() が実行される前に、すべての列挙が終了します。

編集:使用:

return d.Select(e => e.Id).ToList();

...多分よくなる。

于 2011-05-24T16:33:33.547 に答える
0

(より多くの)決定論的usingステートメントと(より決定論的でない)LINQステートメントを混同しています。dそのステートメントでリソースをラップすることusingにより、メソッドの終わりまでにリソースを破棄することを明示的に示しています。

したがって、メソッドを終了する前に確実に破棄したい場合は、、、またはその種類の他のメソッドをd使用してLINQをすぐに実行する必要があります。ToArrayToList

コメント投稿者ごとに)少し複雑パスは、リソース()をLINQステートメントで返し、後で実行できるようにするカスタムを作成することです。つまり、呼び出し元は(通常は単純に)を破棄する責任があります。ブロックを使用して)。IEnumerable<T>dIEnumerable<T>foreach

于 2011-05-24T16:55:09.033 に答える
0

実際、通常のreturn. したがって、Bazメソッドが実行され、戻り、破棄されます。後で結果を列挙するときに、この列挙メカニズムが破棄されたアンマネージ リソースに依存している場合 (これはサンプルの場合である可能性が最も高い)、これは失敗します。

回避策は簡単です。遅延実行を a で防止せず、代わりにreturna を使用しyield returnます。遅延実行を行うための正確なキーワードです。

あなたの方法はこれになります

    IEnumerable<int> Baz()
    {
        using (var d = new SomeDisposableSource())
        {
            //return d.Select(e => e.Id); //Baaaad ! No proper deferred execution
            foreach (var i in d.Select(e => e.Id)) yield return i; //Proper deferred execution
        }
    }

そして、すべてがOKです。は、列挙が完了する前にメソッドusingを呼び出しません。Dispose

于 2011-05-24T18:22:51.490 に答える
0

whether it's possible奇妙な質問です。はい、可能です。メソッドSomeDisposableSourceで破棄されたかどうかを確認できGetEnumeratorます。

于 2011-05-24T16:29:46.557 に答える
0

ジェラルドは正しい方向に進んでいると思いますが、少し異なる方法でコーディングすると、メモリ フットプリントが小さくなる可能性があります。

return d.Select(e => e.Id).ToList();

編集:おっと!IndigoDelta は私よりはるかに進んでいます

于 2011-05-24T16:36:49.270 に答える