2010-09-03 13 views
6

मैं SqlConnection के लिए उपयोग कथन का उपयोग करता हूं। यह प्रदर्शन के लिए अच्छा है क्योंकि निपटान() को कॉल करने वाली ताकतें जो जल्द ही पूल को कनेक्शन जारी करती हैं।क्या कथन का उपयोग घुंघराले ब्रेसिज़ द्वारा प्रतिस्थापित किया जा सकता है?

हालांकि, मुझे एहसास हुआ कि उपयोग में बनाए गए ऑब्जेक्ट को फिर से परिभाषित नहीं किया जा सकता है। मैं इस तरह नहीं कर सकते:

using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     connection.Open(); 
     //... 
     connection = new SqlConnection(connectionString2); 
     //... 
     connection = new SqlConnection(connectionString3); 
    } 

मैं अगर मैं का उपयोग कर की जगह ले सकता सोच रहा था, और कुछ इस तरह करते हैं:

{ 
     SqlConnection connection = new SqlConnection(connectionString); 

     connection.Open(); 
     //... 
     connection = new SqlConnection(connectionString2); 
     //... 
     connection = new SqlConnection(connectionString3); 
} 

SqlConnection पिछले } ब्रेस के बाद उस तक पहुंच नहीं होगा। वस्तु का दायरा खत्म होने पर तुरंत निपटान() को बुलाया जाएगा?

उत्तर

13

नहीं, चीजें आपके दूसरे उदाहरण में स्वचालित रूप से साफ नहीं हो जाएंगी (असल में, आपके पास मौजूद कोड के साथ, आप खुले लटकने वाले कई कनेक्शन छोड़ देंगे)।

इतना ही नहीं, लेकिन using ब्लॉक के अंदर अपवादों को फेंकने के मामले में आप स्वचालित सफाई खो देते हैं। याद रखें कि एक using ब्लॉक में विघटित:

using(SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    connection.Open(); 
    // Do Work 
} 

// First connection is disposed 

using(SqlConnection connection = new SqlConnection(connectionString2)) 
{ 
    // Do More Work 
} 

// Second connection is disposed 

using(SqlConnection connection = new SqlConnection(connectionString3)) 
{ 
    // Do More Work 
} 

// Last connection is dipsosed 
+0

धन्यवाद। अगर कनेक्शन बंद करने की बात आती है तो मैं निश्चित रूप से कनेक्शन कॉल करूँगा। बंद करें() लेकिन मैंने इसे उपरोक्त कोड में नहीं लिखा है। – nan

+1

यदि आप स्पष्ट रूप से बंद() को कॉल करते हैं, तो भी आपके दूसरे उदाहरण में अपवाद होने पर कनेक्शन को खोलने की क्षमता है। कॉल का उपयोग न केवल निष्पादन करता है जब निष्पादन उस ब्लॉक को छोड़ देता है, यह अपवाद होने पर भी इसे कॉल करता है।अच्छे 'usings' समूह के लिए – ThatBlairGuy

3

नहीं, कुछ विशिष्ट क्लीन-अप संरचनाएं बनाता है जो आपको केवल ब्रेसिज़ के साथ नहीं मिलेंगे।

आप परावर्तक का उपयोग करें और आईएल को देखें, तो वहाँ एक फोन अपने लक्ष्य के लिए ब्लॉक का उपयोग की समाप्ति पर जोड़ा निपटान के लिए है:

L_0006: newobj instance void [System.Data]System.Data.SqlClient.SqlConnection::.ctor(string) 
L_000b: stloc.0 
L_000c: nop 
L_000d: nop 
L_000e: leave.s L_0020 
L_0010: ldloc.0 
L_0011: ldnull 
L_0012: ceq 
L_0014: stloc.1 
L_0015: ldloc.1 
L_0016: brtrue.s L_001f 
L_0018: ldloc.0 
**L_0019: callvirt instance void [mscorlib]System.IDisposable::Dispose()** 
L_001e: nop 
L_001f: endfinally 

यही कारण है कि आप अंदर एक नया कनेक्शन नहीं बना सकता ब्लॉक का उपयोग करके और इसे चर के लिए असाइन करें - ऐसा करने से मूल संदर्भ लटकना और अनदेखा छोड़ दिया जाएगा।

+1

मैं इसे IDisposable वस्तुओं पर निपटान() कहता है लगता है ... यकीन –

+1

@Mike के लिए पता नहीं है - आप केवल IDisposable वस्तुओं पर using' उपयोग कर सकते हैं 'क्योंकि यह (निपटान() – annakata

+3

यह वास्तव में कॉल कॉल' (IDisposable) blah)। उद्देश्य() ', जहां 'blah' उपयोग चर है। यह संकलित नहीं करता है अगर प्रकार 'IDisposable' लागू नहीं करता है। – Timwi

3

नहीं, इसे बंद घुंघराले ब्रेस के बाद नहीं बुलाया जाएगा। आपको इसे मैन्युअल रूप से कॉल करने या using कथन का उपयोग करने की आवश्यकता है।

यदि आप निपटान निष्पादित नहीं करते हैं तो इसे अंतिम रूप देने पर निष्पादित किया जाएगा। और यहां आपके पास 2 समस्याएं हैं

  • अंतिमकरण विधि निष्पादित करना प्रदर्शन के लिए महंगा है। यदि आपकी निपटान विधि पहले से ही ऑब्जेक्ट को साफ करने के लिए काम कर चुकी है, तो कचरा कलेक्टर के लिए ऑब्जेक्ट की अंतिम विधि को कॉल करने के लिए जरूरी नहीं है (यदि यह अच्छी तरह कार्यान्वित किया गया है, तो एक निपटान विधि को उस ऑब्जेक्ट के लिए SuppressFinalize विधि को कॉल करना चाहिए)। (MSDN)
  • आप उस क्षण को नियंत्रित नहीं करते हैं जब अंतिम रूप को स्वचालित रूप से बुलाया जाता है और निष्पादित नहीं किया जा सकता है (उदाहरण के लिए एक क्रैश)।
8

using बयान वाक्यात्मक चीनी है कि वस्तुओं () भीतर प्रारंभ पर Dispose कॉल है, तो आप बस इसे नहीं बदल सकते हैं जैसा कि आप अपने उदाहरण में है।

आप ध्यान दें कि using कथन के भीतर आप केवल उन्हीं वस्तुओं का उपयोग कर सकते हैं जो IDisposable लागू करते हैं, जो सुनिश्चित करता है कि Dispose कहा जा सकता है। इस के लिए

using (MyResource myRes = new MyResource()) 
{ 
    myRes.DoSomething(); 

} 

: this लेख में बताया गया

के रूप में, संकलक इस बदलना होगा

MyResource myRes= new MyResource(); 
try 
{ 
    myRes.DoSomething(); 
} 
finally 
{ 
    if (myRes!= null) 
     ((IDisposable)myRes).Dispose(); 
} 

तो, जब तक आप इस संरचना नकल, आप एक ही व्यवहार नहीं मिलेगा।

इसके अलावा - आपके उदाहरण में एक वैरिएबल का उपयोग करने का तरीका खराब अभ्यास है।कोई भी जो कोड पढ़ता है, वह सोच सकता है कि वे कनेक्शन 1 देख रहे हैं जब वे वास्तव में 2 या 3 देख रहे हैं। बहुत भ्रमित हो सकता है और सड़क के नीचे सभी प्रकार की समस्याएं पैदा हो सकती हैं।

+0

वैसे मैंने उपयोग से छुटकारा पाने की कोशिश की क्योंकि मेरे पास उनमें से बहुत सारे हैं (मैं उन्हें अक्सर अपने प्रोजेक्ट में 'स्ट्रीम' के साथ भी उपयोग करता हूं)। दूसरा कारण यह है कि मेरे पास बहुत से अनुक्रमिक कनेक्शन हैं इसलिए मैंने एक ऑब्जेक्ट का उपयोग करने के बारे में सोचा। मैं सुगमता बढ़ाना चाहता था लेकिन आप सही हैं कि यह सिर्फ इसे कम कर सकता है। – nan

3
using(foo) 
{ 
    // stuff 
} 
: तुम सच में अलग कनेक्शन का उपयोग कर रहे हैं और प्रत्येक कनेक्शन ब्लॉक के अंत में का निपटारा किया जाता है तो

SqlConnection connection = new SqlConnection(connectionString); 
try 
{ 
    connection.Open(); 
    // Do work 
} 
finally 
{ 
    connection.Dispose(); 
} 

, मैं कई का उपयोग कर ब्लॉक का प्रयोग करेंगे

try 
{ 
    // stuff 
} 
finally 
{ 
    foo.Dispose() 
} 

जबकि:

... जो में तब्दील चीनी का एक सा है

{ 
    // stuff 
} 

... किसी भी चीज़ में अनुवाद नहीं करता है। यह सिर्फ है:

{ 
    // stuff 
} 

: डी

संपादित करें:।। कृपया स्वरूपण जब आप :(

2

नहीं, आप ऐसा नहीं कर सकते कम से कम सी # में संपादित नष्ट नहीं है

लेकिन आप कथन का उपयोग एक के अंदर विभिन्न डिस्पोजेबल वस्तुओं बना सकते हैं:

using (SqlConnection connection1 = new SqlConnection(connectionString1), 
      connection2 = new SqlConnection(connectionString2), 
      connection3 = new SqlConnection(connectionString3)) 
    { 
     connection1.Open(); 
     //... 
     connection2.Open(); 
     //... 
     connection3.Open(); 
    } 

C++/CLI आप ढेर की तरह faision में अपने प्रयोज्य कक्षाओं का उपयोग हो सकता है:

void MyClass::Foo() 
{ 

{ 
    SqlConnection connection(connectionString); 
    //connection still allocated on the managed heap 
    connection.Open(); 
    ... 
    //connection will be automatically disposed 
    //when the object gets out of scope 
} 


{ 
    SqlConnection connection(connectionString2); 
    connection2.Open(); 
    ... 
} 

} 
+0

+1, उस बारे में नहीं पता था – nan

1

मैं पहली बार में भी इस बारे में सोचा ... लेकिन जाहिरा तौर पर उपयोग करते समय ब्लॉक समाप्त हो जाती है, .Dispose() अपने वस्तु है, जो पर कहा जाता है ऑब्जेक्ट को दायरे से बाहर जाने देने से अलग। चूंकि सी # एक कचरा एकत्रित भाषा है, इसलिए आपकी वस्तु वास्तव में साफ होने में समय लग सकता है। using ब्लॉक सुनिश्चित करता है कि यह तुरंत निपटान किया गया है, और किसी भी अपवाद के बावजूद।

संबंधित मुद्दे