Kullanıcı kokos , C # sorusunun harika Gizli Özellikleriniusing
anahtar kelimeden bahsederek yanıtladı . Bunu biraz açıklayabilir misin? Ne işe yarar using
?
Kullanıcı kokos , C # sorusunun harika Gizli Özellikleriniusing
anahtar kelimeden bahsederek yanıtladı . Bunu biraz açıklayabilir misin? Ne işe yarar using
?
Yanıtlar:
İfadenin nedeni using
, nesnenin kapsam dışına çıkar çıkmaz atılmasını sağlamaktır ve bunun gerçekleşmesini sağlamak için açık kod gerektirmez.
Olduğu gibi C # (codeproject) 'de 'kullanarak' ifadesi anlama ve IDisposable (microsoft) uygulamak nesneleri kullanarak , C # derleyicisi dönüştürür
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
için
{ // Limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes != null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
C # 8, " bildirimleri kullanarak " adlı yeni bir sözdizimi sunar :
Kullanım bildirimi, önce using anahtar sözcüğünden önce gelen değişken bir bildirimdir. Derleyiciye bildirilen değişkenin kapalı alanın sonuna yerleştirilmesi gerektiğini söyler.
Yani yukarıdaki eşdeğer kod şöyle olacaktır:
using var myRes = new MyResource();
myRes.DoSomething();
Ve kontrol içeren kapsamı terk ettiğinde (genellikle bir yöntem, ancak aynı zamanda bir kod bloğu da olabilir), myRes
atılacaktır.
using
emin olur Dispose
.
MyRessource
Bir yapı olduğunda oluşturulan kodun biraz farklı olduğunu lütfen unutmayın . Açıkçası hükümsüzlük testi yok, aynı zamanda boks yapmak da yok IDisposable
. Kısıtlı bir sanal çağrı gönderilir.
using
, içine inşa değişken salt okunur. Yerel değişkenler için using
deyim olmadan bunu başarmanın bir yolu yoktur .
Birçok insan hala yaptığı için:
using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
//code
}
Sanırım bir çok insan hala yapabileceğinizi bilmiyor:
using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
//code
}
Böyle şeyler:
using (var conn = new SqlConnection("connection string"))
{
conn.Open();
// Execute SQL statement here on the connection you created
}
Bu SqlConnection
, .Close()
işlevi açıkça çağırmaya gerek kalmadan kapatılacaktır ve bu, bir / / gereksinimi olmadan bir istisna atılmış olsa bile gerçekleşecektir .try
catch
finally
return
, using
bloğun ortasından olsanız bile bağlantı hala kapalı olacaktır .
kullanarak, anlamında
using (var foo = new Bar())
{
Baz();
}
Aslında denemek için bir steno / nihayet blok. Bu koda eşdeğerdir:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
Tabii ki, ilk snippet'in ikinciden çok daha özlü olduğunu ve ayrıca bir istisna atılmış olsa bile temizleme olarak yapmak isteyebileceğiniz birçok şey olduğunu not edeceksiniz. Bu nedenle, Dispose yönteminde rasgele kod çalıştırmanıza izin veren Scope olarak adlandırdığımız bir sınıf bulduk. Örneğin, bir işlemi gerçekleştirmeye çalıştıktan sonra her zaman false olarak ayarlamak istediğiniz IsWorking adlı bir özelliğiniz varsa, bunu şu şekilde yaparsınız:
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
Çözümümüz ve burada nasıl elde ettiğimiz hakkında daha fazla bilgi edinebilirsiniz .
Microsoft belgelerine durumları kullanarak bir çifte fonksiyonuna sahiptir ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx bir şekilde her ikisi), direktif ve ifadeleri . Bir açıklama olarak , burada diğer cevaplarda belirtildiği gibi, anahtar kelime, IDisposable bir nesneyi elden çıkarmak için bir kapsam belirlemek için sözdizimsel şekerdir . Bir yönerge olarak , ad alanlarını ve türlerini almak için rutin olarak kullanılır. Ayrıca yönerge olarak, oluşturabileceğiniz takma adları kitapta sivri out gibi, ad ve türleri için "Ceviz Kabuğundaki C # 5.0: Kesin Kılavuzu" ( http://www.amazon.com/5-0-Nutshell-The- Kesin-Referans-e-kitap / dp / B008E6I1K8), Joseph ve Ben Albahari. Bir örnek:
namespace HelloWorld
{
using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
public class Startup
{
public static AppFunc OrderEvents()
{
AppFunc appFunc = (IDictionary<DateTime, string> events) =>
{
if ((events != null) && (events.Count > 0))
{
List<string> result = events.OrderBy(ev => ev.Key)
.Select(ev => ev.Value)
.ToList();
return result;
}
throw new ArgumentException("Event dictionary is null or empty.");
};
return appFunc;
}
}
}
Bu, akıllıca benimsenecek bir şeydir, çünkü bu uygulamanın kötüye kullanılması kişinin kodunun netliğine zarar verebilir. DotNetPearls'da ( http://www.dotnetperls.com/using-alias ) C # takma adlarıyla ilgili artıları ve eksileri de anlatan güzel bir açıklama var .
using
. Kodu okurken kafam karıştı - zaten System.Collections
var olduğunu ve IEnumerable<T>
sınıfı olduğunu biliyorum . Başka bir ad vermek için bir takma ad kullanmak, onu benim için gizliyor. Daha using FooCollection = IEnumerable<Foo>
sonra geliştiricilerin kodu okumasını ve "Cehennem nedir FooCollection
ve neden bir yerde bunun için bir sınıf yok " diye düşünmesini sağlamanın bir yolu olarak görüyorum . Asla kullanmam ve kullanımını caydırırdım. Ama bu sadece ben olabilirim.
Geçmişte giriş ve çıkış akışlarıyla çalışmak için çok kullandım. Onları güzelce iç içe yerleştirebilirsiniz ve genellikle karşılaştığınız birçok potansiyel sorunu ortadan kaldırır (otomatik olarak imha çağrısı yaparak). Örneğin:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (System.IO.StreamReader sr = new StreamReader(bs))
{
string output = sr.ReadToEnd();
}
}
}
Sadece şaşırdığım küçük bir şey eklemek gelmedi. Kullanmanın en ilginç özelliği (benim görüşüme göre), kullanım bloğundan nasıl çıkacağınızı bilmediğinizde, nesneyi her zaman atacaktır. Buna iadeler ve istisnalar dahildir.
using (var db = new DbContext())
{
if(db.State == State.Closed) throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
Kural dışı durumun atılması veya listenin döndürülmesi önemli değildir. DbContext nesnesi her zaman atılır.
Kullanmanın bir başka harika kullanımı, kalıcı bir iletişim kutusu başlatılmasıdır.
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
Eğer bir türde bir yerel değişken kullandığınızda Sonuç olarak uygular o IDisposable
, her zaman , istisnasız kullanmak using
1 .
Eğer yerel olmayan kullanırsanız IDisposable
değişkenleri, o zaman her zaman uygulamak IDisposable
deseni .
İki basit kural, istisna yok 1 . Aksi halde kaynak sızıntılarını önlemek * ss'de gerçek bir acıdır.
1) : Tek istisna - istisnaları ele alırken. Daha sonra blokta Dispose
açıkça çağırmak daha az kod olabilir finally
.
Diğer ad ad alanını aşağıdaki örnekle kullanabilirsiniz:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
Bu, gördüğünüz gibi bir takma ad yönergesi olarak adlandırılır , kodunuzda referansta bulunduğunuz şeyi açıkça belirtmek istiyorsanız uzun soluklu referansları gizlemek için kullanılabilir.
LegacyEntities.Account
onun yerine
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
ya da sadece
Account // It is not obvious this is a legacy entity
İlginç bir şekilde, / IDisposable şablonunu diğer ilginç şeyler için de kullanabilirsiniz (Rhino Mocks'ın kullandığı yolun diğer noktası gibi). Temel olarak, derleyicinin her zaman "kullanılmış" nesneyi çağırması gerçeğinden yararlanabilirsiniz . Belirli bir işlemden sonra gerçekleşmesi gereken bir şey varsa ... kesin bir başlangıç ve bitişe sahip bir şey ... o zaman basitçe işlemi kurucuda başlatan ve sonra Dispose yönteminde biten IDisposable sınıfını yapabilirsiniz.
Bu, söz konusu işlemin açık başlangıcını ve sonunu belirtmek için gerçekten güzel bir sözdizimi kullanmanızı sağlar. System.Transactions işi de böyle çalışır.
ADO.NET kullanırken bağlantı nesnesi veya okuyucu nesnesi gibi şeyler için anahtar çalışmasını kullanabilirsiniz. Bu şekilde kod bloğu tamamlandığında bağlantınız otomatik olarak imha edilir.
"kullanma" ad alanı çakışmalarını gidermek için de kullanılabilir. Konuyla ilgili yazdığım kısa bir eğitim için bkz. Http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ .
public class ClassA:IDisposable
{
#region IDisposable Members
public void Dispose()
{
GC.SuppressFinalize(this);
}
#endregion
}
public void fn_Data()
{
using (ClassA ObjectName = new ClassA())
{
//use objectName
}
}
using , kullanıldıktan sonra atılmasını istediğiniz bir kaynağınız olduğunda kullanılır.
Örneğin, bir Dosya kaynağı tahsis ediyorsanız ve küçük bir okuma veya yazma için kodun yalnızca bir bölümünde kullanmanız gerekiyorsa, kullanma işlemi biter bitmez Dosya kaynağının atılması için kullanışlıdır.
Kullanılan kaynağın düzgün çalışması için IDisposable uygulaması gerekir.
Misal:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
Using anahtar sözcüğü, nesnenin kapsamını tanımlar ve kapsam tamamlandığında nesneyi atar. Örneğin.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Anahtar kelimeyi C # kullanarak MSDN makalesi için buraya bakın .
Son derece önemli olduğu için değil, aynı zamanda kaynakları anında değiştirmek için de kullanılabilir. Evet, daha önce de belirtildiği gibi tek kullanımlıktır, ancak belki de özellikle yürütme işleminizin geri kalanında diğer kaynaklarla uyumsuz oldukları kaynakları istemezsiniz. Yani başka yere müdahale etmeyecek şekilde atmak istiyorsunuz.
Aşağıdaki yorumlar sayesinde, bu yazıyı biraz temizleyeceğim (o zaman 'çöp toplama' kelimelerini
kullanmamalıydım , özür dilerim): Kullanırken, nesnede Dispose () yöntemini çağırır kullanım kapsamının sonunda. Böylece Dispose () yönteminizde oldukça büyük bir temizleme koduna sahip olabilirsiniz.
Umarım bu işaretlenmemiş olabilir bir madde işareti: IDisposable uygularsanız, Dispose () uygulamanızda GC.SuppressFinalize () 'i çağırdığınızdan emin olun, aksi takdirde otomatik çöp toplama gelip bazılarında Sonlandırmaya çalışır zaten imha ettiyseniz en azından kaynak israfı olacaktır.
Nesnenin hemen atıldığı makul bir kullanımın başka bir örneği:
using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString))
{
while (myReader.Read())
{
MyObject theObject = new MyObject();
theObject.PublicProperty = myReader.GetString(0);
myCollection.Add(theObject);
}
}
Kıvırcık parantezlerin dışındaki her şey atılır, bu nedenle nesnelerinizi kullanmıyorsanız atmak harikadır. SqlDataAdapter nesneniz varsa ve uygulama yaşam döngüsünde yalnızca bir kez kullanıyorsanız ve yalnızca bir veri kümesini dolduruyorsanız ve artık buna ihtiyacınız yoksa, kodu kullanabilirsiniz:
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
Using ifadesi, IDisposable nesneleri doğru kullanmak için bir kolaylık mekanizması sağlar. Kural olarak, IDisposable nesnesini kullandığınızda, bunu bir using deyiminde bildirmeli ve başlatmalısınız. Using ifadesi, nesne üzerindeki Dispose yöntemini doğru şekilde çağırır ve (daha önce gösterildiği gibi kullandığınızda), Dispose çağrılır çağrılmadığında nesnenin kendisinin kapsam dışına çıkmasına da neden olur. Kullanım bloğunda, nesne salt okunurdur ve değiştirilemez veya yeniden atanamaz.
Bu buradan geliyor:
Örnek için kapsam oluşturmak için de kullanılabilir:
class LoggerScope:IDisposable {
static ThreadLocal<LoggerScope> threadScope =
new ThreadLocal<LoggerScope>();
private LoggerScope previous;
public static LoggerScope Current=> threadScope.Value;
public bool WithTime{get;}
public LoggerScope(bool withTime){
previous = threadScope.Value;
threadScope.Value = this;
WithTime=withTime;
}
public void Dispose(){
threadScope.Value = previous;
}
}
class Program {
public static void Main(params string[] args){
new Program().Run();
}
public void Run(){
log("something happend!");
using(new LoggerScope(false)){
log("the quick brown fox jumps over the lazy dog!");
using(new LoggerScope(true)){
log("nested scope!");
}
}
}
void log(string message){
if(LoggerScope.Current!=null){
Console.WriteLine(message);
if(LoggerScope.Current.WithTime){
Console.WriteLine(DateTime.Now);
}
}
}
}
Using ifadesi, .NET'e artık gerekli olmadığında using blokunda belirtilen nesneyi bırakmasını söyler. Bu nedenle, System.IO Türleri gibi, onlardan sonra temizlenmesi gereken sınıflar için 'using' bloğunu kullanmalısınız.
using
Anahtar kelimenin C # içinde aşağıdaki gibi iki kullanımı vardır .
Direktif olarak
Genel olarak, using
arka plan kod ve sınıf dosyalarına ad alanları eklemek için anahtar kelimeyi kullanırız . Ardından tüm sınıfları, arayüzleri ve soyut sınıfları ve bunların mevcut sayfadaki yöntemlerini ve özelliklerini kullanılabilir hale getirir.
Misal:
using System.IO;
Bir açıklama olarak
Bu, using
anahtar kelimeyi C # 'da kullanmanın başka bir yoludur . Çöp Toplama'daki performansı iyileştirmede hayati bir rol oynar.
using
Dispose ifadesi olmasını sağlar () nesneleri oluşturma ve yöntemleri, özellikleri çağıran ve benzeri olduğunda bir durum meydana gelse bile denir. Dispose (), özel Çöp Toplama'nın uygulanmasına yardımcı olan IDisposable arabiriminde bulunan bir yöntemdir. Başka bir deyişle, bazı veritabanı işlemi (Ekle, Güncelleştir, Sil) yapıyorum ama bir şekilde bir istisna oluşursa, burada using deyimi bağlantıyı otomatik olarak kapatır. Bağlantı Close () yöntemini açıkça çağırmanıza gerek yoktur.
Bir diğer önemli faktör ise Bağlantı Havuzu Oluşturmada yardımcı olmasıdır. .NET'te Bağlantı Havuzu Oluşturma, bir veritabanı bağlantısının birden çok kez kapatılmasını önlemeye yardımcı olur. Bağlantı nesnesini ileride kullanmak üzere bir havuza gönderir (sonraki veritabanı çağrısı). Uygulamanızdan bir sonraki veritabanı bağlantısı çağrıldığında, bağlantı havuzu havuzdaki kullanılabilir nesneleri getirir. Böylece uygulamanın performansını artırmaya yardımcı olur. Using ifadesini kullandığımızda, denetleyici nesneyi bağlantı havuzuna otomatik olarak gönderir, Close () ve Dispose () yöntemlerini açıkça çağırmaya gerek yoktur.
Try-catch bloğunu kullanarak using deyiminin yaptığıyla aynı şeyi yapabilir ve nihayet blok içinde açıkça Dispose () öğesini çağırabilirsiniz. Ancak using ifadesi, kodu daha temiz ve daha zarif hale getirmek için çağrıları otomatik olarak yapar. Kullanım bloğunda, nesne salt okunurdur ve değiştirilemez veya yeniden atanamaz.
Misal:
string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
}
}
Önceki kodda herhangi bir bağlantıyı kapatmıyorum; otomatik olarak kapanacaktır. using
İfadesi nedeniyle otomatik) conn.Close (arayacak using
deyimi ( using (SqlConnection conn = new SqlConnection(connString)
) ve bir SqlDataReader nesnesi için aynı. Ayrıca herhangi bir istisna oluşursa bağlantı otomatik olarak kapanır.
Daha fazla bilgi için, bkz . C # 'da Kullanmanın Kullanımı ve Önemi .
Rhino Mocks Kayıt oynatma sözdizimi ilginç kullanır using
.
deyim olarak kullanıldığında, belirtilen nesneye otomatik olarak atama çağrılır. Nesne, IDisposable arabirimini uygulamalıdır. Bir ifadede aynı türden olduğu sürece birkaç nesne kullanmak mümkündür.
CLR kodunuzu MSIL'e dönüştürür. Using ifadesi denemeye dönüştürülür ve sonunda engellenir. Using ifadesi IL'de bu şekilde temsil edilir. Using ifadesi üç bölüme çevrilir: edinme, kullanma ve elden çıkarma. Kaynak önce edinilir, daha sonra kullanım son olarak bir cümle ile bir try deyimine eklenir. Nesne daha sonra nihayet fıkrasında yer alır.
Belirli bir değişkenin kapsamını tanımlamak için Cümle Kullanımı kullanılır. Örneğin:
Using(SqlConnection conn=new SqlConnection(ConnectionString)
{
Conn.Open()
// Execute sql statements here.
// You do not have to close the connection explicitly here as "USING" will close the connection once the object Conn becomes out of the defined scope.
}