Using () ifadesinin içinden dönmenin herhangi bir yan etkisi var mı?


125

Bir yöntem değerini döndürme içeride bir DataContext'i alır using ifadesinde her zaman iş gibi görünüyor cezası bu gibi:

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

Ben edilmelidir gibi Ama her zaman hissetmek şey kapanış ben işlem tanımlayarak kullanarak parantez, örneğin dışarı kırmadan önce , using ifadesi 's değeri elde içeride dönen sonra parantez ve sonra parantez.

Değişkeni parantez kullanmanın dışında tanımlamak ve döndürmek daha iyi bir uygulama olur mu yoksa kaynakları herhangi bir şekilde korur mu?


1
Bunun varyantları için genel IL'ye bakmak ilginç olabilir. Üretilen IL'de çok az fark olacağından şüpheleniyorum. Normalde var işlemini bildirmekle bile uğraşmazdım - sadece ifadenin sonucunu döndür.
Jonesie

Yanıtlar:


164

Hayır, bence bu şekilde daha net. Değil, endişe Do Dispose"Çıkarken" hala adı verilecek - ve sadece sonra dönüş değeri tam değerlendirilir. Herhangi bir noktada bir istisna atılırsa (dönüş değerinin değerlendirilmesi dahil) Disposeyine de çağrılacaktır.

Kesinlikle daha uzun rotayı alabilecek olsanız da , (zihinsel olarak) takip etmek için sadece kaba ve ekstra bağlam ekleyen iki ekstra çizgi. Aslında, fazladan yerel değişkene gerçekten ihtiyacınız yoktur - ancak hata ayıklama açısından kullanışlı olabilir. Sen olabilir sadece var:

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

Aslında, nokta notasyonu kullanma ve Wherekoşulu şunun içine koyma cazip gelebilir 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
Sine bu sensin @jon, kullanım bloğunun içine bir istisna atılırsa hala güvenli mi?
Dave Archer

6
Evet. kullanmak, deneme / nihayet oluşturma için basitçe sözdizimsel şekerdir
Mitch Wheat

@David: Mitch'in dediği gibi, sorun değil - Bunu daha net hale getirmek için cevabı güncelledim :)
Jon Skeet

2
Neden OrderByDescending'i SingleOrDefault ile birlikte kullanmalı?
erikkallen

2
@erikkallen: LINQ'da maalesef "MaxBy" yok - bu yüzden maksimum değeri olan satırı alamazsınız. LINQ to Objects için kendinizinkini oldukça kolay bir şekilde yazabilirsiniz, ancak bu durumda bunu yapmanın daha iyi bir yolu olduğundan emin değilim. Bunun yerine ne önerirsiniz?
Jon Skeet

32

Şuna bir bak

C # 'da' using 'ifadesini anlama

CLR, kodunuzu MSIL'e dönüştürür. Ve using ifadesi bir denemeye ve sonunda bloğa çevrilir. Bu, kullanım deyiminin IL'de temsil edilme şeklidir. Kullanım ifadesi üç kısma çevrilir: edinme, kullanım ve elden çıkarma. Kaynak önce alınır, ardından kullanım, bir last cümlesiyle birlikte bir try deyimine eklenir. Nesne daha sonra nihayet yan tümcesine yerleştirilir.


4
İlginç bir fikir. Teşekkürler.
Kangkan

1
Bu, soruyu şu ifadeye çevirir: Bir dene-sonunda dene-bloğundan dönmenin herhangi bir yan etkisi var mı?
Henk Holterman

3

6

Orada hiçbir bir iç dönen yan etkileri using()açıklamada.

En okunabilir kodu yapıp yapmadığı ise başka bir tartışmadır.


0

Sanırım hepsi aynı. Kodda kötü bir şey yok. .NET çerçevesi, nesnenin nerede oluşturulduğuyla ilgilenmez. Önemli olan, referans verilip verilmediğidir.


-1

Evet, bir yan etkisi olabilir. Örneğin, ASP.NET MVC Action yönteminde aynı tekniği kullanırsanız, şu hatayı alırsınız: "ObjectContext örneği atıldı ve artık bağlantı gerektiren işlemler için kullanılamaz"

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
ifadesinden başka bir işlem tanımlarsanız, aynı hatayı alırsınız. anahtar kelime kullanmak bu durumda ilgisizdir.
Costa
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.