using()ステートメント内から戻ることによる副作用はありますか?


125

DataContextを取得するusingステートメントからメソッド値を返すと、次のように常に正常に動作するようです。

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        var transaction = (from t in db.Transactions
                              orderby t.WhenCreated descending
                              where t.Id == singleId
                              select t).SingleOrDefault();
        return transaction;
    }
}

しかし、私はいつも私がしなければならないように感じる何かを閉じて、私が使用してブラケットを抜け出す前にトランザクションを定義することによって、例えば、前にそれの値を取得し、使用して文の内側ブラケット、その後、帰国後に括弧。

括弧を使用して変数を定義して返すことは、何らかの方法でリソースを節約するより良い方法でしょうか?


1
これの変種について一般的なILを見るのは興味深いかもしれません。生成されたILにはほとんど違いがないと思います。私は通常、varトランザクションを宣言する手間すらしません。式の結果を返すだけです。
Jonesie

回答:


164

いいえ、この方が明確だと思います。心配しないでください、Disposeそれでも「途中」と呼ばれます-と戻り値が完全に評価された。例外がスローされた場合(戻り値の評価を含む)Disposeも呼び出されます。

あなたは確かに長いルートをとることができますが、(精神的に)追跡するために残骸と余分なコンテキストを追加するのは2つの余分な行です。実際、追加のローカル変数は実際には必要ありませんが、デバッグに関しては便利です。あなたただ持つことができます:

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        return (from t in db.Transactions
                orderby t.WhenCreated descending
                where t.Id == singleId
                select t).SingleOrDefault();
    }
}

確かに、私はドット表記を使いたくて、Where条件をの中に入れたくなるかもしれませんSingleOrDefault

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        return db.Transactions.OrderByDescending(t => t.WhenCreated)
                              .SingleOrDefault(t => t.Id == singleId);
    }
}

2
@jonのサインですが、usingブロック内で例外がスローされても安全ですか?
デイブアーチャー

6
はい。usingは、try / finallyコンストラクトの単純な構文糖です
Mitch Wheat

@David:ミッチが言うように、それは結構です-私はそれをより明確にするために答えを更新しました:)
Jon Skeet

2
OrderByDescendingをSingleOrDefaultと組み合わせて使用​​する理由
erikkallen

2
@erikkallen:LINQには「MaxBy」がありません。残念ながら、最大値の行を取得することはできません。LINQ to Objectsの場合は、独自に簡単に作成できますが、この場合にそれを行うためのより良い方法はわかりません。代わりに何を提案しますか?
Jon Skeet

32

これを見てください

C#の「using」ステートメントについて

CLRはコードをMSILに変換します。そしてusingステートメントはtryに変換され、最終的にブロックされます。これは、ILでusingステートメントを表す方法です。usingステートメントは、取得、使用、廃棄の3つの部分に変換されます。最初にリソースが取得され、次に使用法がfinally節を含むtryステートメントで囲まれます。オブジェクトは、finally句に配置されます。


4
興味深い洞察。ありがとう。
2010

1
これは、質問を次のように変換します。try-finallyのtryブロックから戻ることによる副作用はありますか?
ヘンクホルターマン

3
いいえ、finallyは常に呼び出されます。techinterviews.com/interview-questions-for-c-developers
Adriaan Stander

6

ステートメント内から戻ることによる副作用はありませんusing()

それが最も読みやすいコードになるかどうかは別の議論です。


0

それはすべて同じだと思います。コードに悪いことは何もありません。.NETフレームワークは、オブジェクトが作成される場所を気にしません。重要なのは、それが参照されているかどうかです。


-1

はい、副作用がある可能性があります。たとえば、ASP.NET MVCアクションメソッドで同じ手法を使用すると、「ObjectContextインスタンスが破棄され、接続を必要とする操作に使用できなくなりました」というエラーが発生します。

public ActionResult GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        var transaction = (from t in db.Transactions
                              orderby t.WhenCreated descending
                              where t.Id == singleId
                              select t).SingleOrDefault();
        return PartialView("_transactionPartial", transaction);
    }
}

2
usingステートメント以外でトランザクションを定義すると、同じエラーが発生します。この場合、キーワードの使用は無関係です。
コスタ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.