Apakah ada efek samping dari kembali dari menggunakan pernyataan ()?

125

Mengembalikan nilai metode dari dalam pernyataan menggunakan yang mendapat DataContext tampaknya selalu berfungsi dengan baik , seperti ini:

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

Tapi saya selalu merasa harus menutup sesuatu sebelum saya keluar dari tanda kurung menggunakan, misalnya dengan mendefinisikan transaksi sebelum pernyataan menggunakan, mendapatkan nilainya di dalam tanda kurung, dan kemudian kembali setelah tanda kurung.

Apakah mendefinisikan dan mengembalikan variabel di luar tanda kurung menggunakan praktik yang lebih baik atau menghemat sumber daya dengan cara apa pun?

Edward Tanguay
sumber
1
Mungkin menarik untuk melihat IL umum untuk varian ini. Saya menduga bahwa akan ada sedikit perbedaan dalam IL yang dihasilkan. Saya biasanya tidak akan repot-repot menyatakan transaksi var - hanya mengembalikan hasil dari ekspresi.
Jonesie

Jawaban:

164

Tidak, saya pikir ini lebih jelas. Jangan khawatir, Disposemasih akan dipanggil "di jalan keluar" - dan hanya setelah nilai kembali sepenuhnya dievaluasi. Jika pengecualian dilemparkan pada titik mana pun (termasuk mengevaluasi nilai pengembalian) Disposemasih akan dipanggil juga.

Meskipun Anda tentu saja bisa mengambil rute yang lebih panjang, itu adalah dua baris tambahan yang hanya menambahkan konteks kasar dan ekstra untuk melacak (secara mental). Bahkan, Anda tidak benar-benar membutuhkan variabel lokal tambahan - meskipun bisa berguna dalam hal debugging. Anda bisa saja:

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

Memang, saya bahkan mungkin tergoda untuk menggunakan notasi titik, dan menempatkan Wherekondisi dalam SingleOrDefault:

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        return db.Transactions.OrderByDescending(t => t.WhenCreated)
                              .SingleOrDefault(t => t.Id == singleId);
    }
}
Jon Skeet
sumber
2
Sine itu kamu @jon, apakah masih aman jika pengecualian dilemparkan ke dalam blok menggunakan?
Dave Archer
6
Iya. menggunakan hanyalah sintaksis gula untuk mencoba / akhirnya membangun
Mitch Wheat
@ David: Seperti kata Mitch, tidak apa-apa - Saya telah memperbarui jawaban untuk membuatnya lebih jelas :)
Jon Skeet
2
Mengapa menggunakan OrderByDescending dalam kombinasi dengan SingleOrDefault?
erikkallen
2
@ erikkallen: LINQ tidak memiliki "MaxBy", sayangnya - jadi Anda tidak bisa mendapatkan baris dengan nilai maksimal. Untuk LINQ to Objects Anda dapat menulis sendiri dengan cukup mudah, tetapi saya tidak yakin cara yang lebih baik dalam hal ini. Apa yang akan Anda sarankan sebagai gantinya?
Jon Skeet
32

Lihatlah ini

Memahami pernyataan 'menggunakan' di C #

CLR mengubah kode Anda menjadi MSIL. Dan statemen penggunaan diterjemahkan menjadi blok percobaan dan akhirnya. Ini adalah bagaimana pernyataan penggunaan diwakili dalam IL. Pernyataan menggunakan diterjemahkan menjadi tiga bagian: akuisisi, penggunaan, dan pembuangan. Sumber daya pertama kali diperoleh, kemudian penggunaannya dilampirkan dalam pernyataan coba dengan klausa akhirnya. Objek kemudian dibuang di klausa akhirnya.

Adriaan Stander
sumber
4
Wawasan yang menarik. Terima kasih.
Kangkan
1
Itu menerjemahkan pertanyaan menjadi: Adakah efek samping dari kembali dari coba-akhirnya?
Henk Holterman
3
Tidak, akhirnya akan selalu dipanggil. techinterviews.com/interview-questions-for-c-developers
Adriaan Stander
6

Tidak ada efek samping dari kembali dari dalam using()pernyataan.

Apakah itu membuat kode yang paling mudah dibaca adalah diskusi lain.

Mitch Wheat
sumber
0

Saya pikir, semua sama saja. Tidak ada yang buruk dalam kode. Kerangka NET. Tidak peduli di mana objek dibuat. Yang penting adalah apakah itu direferensikan atau tidak.

Kerido
sumber
-1

Ya, bisa ada efek samping. Misalnya, jika Anda menggunakan teknik yang sama dalam metode ASP.NET MVC Action, Anda akan mendapatkan kesalahan berikut: "Contoh ObjectContext telah dibuang dan tidak lagi dapat digunakan untuk operasi yang memerlukan koneksi"

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);
    }
}
BermanfaatBee
sumber
2
jika Anda mendefinisikan transaksi di luar menggunakan pernyataan, Anda akan mendapatkan kesalahan yang sama. menggunakan kata kunci tidak terkait dalam hal ini.
Costa