क्या {} स्टेटमेंट का उपयोग करके कॉल को रिटर्न के अंदर रखना एक अच्छा तरीका है?


93

मैं सिर्फ यह जानना चाहता हूं कि returnकिसी usingब्लॉक के अंदर कॉल करना सुरक्षित / अच्छा तरीका है ।

पूर्व के लिए।

using(var scope = new TransactionScope())
{
  // my core logic
  return true; // if condition met else
  return false;
  scope.Complete();
}

हम जानते हैं कि सबसे अंतिम कर्ली ब्रेस dispose()को कहा जाता है। लेकिन उपरोक्त मामले में क्या होगा, क्योंकि returnदिए गए दायरे से बाहर नियंत्रण कूदता है (AFAIK) ...

  1. क्या मेरा scope.Complete()कहा जाता है?
  2. और इसलिए गुंजाइश की dispose()विधि के लिए।

1
एक बार जब using{}गुंजाइश खत्म हो जाती है, तो संबंधित वस्तुओं का निस्तारण हो जाता है, returnइस दायरे को "तोड़" देगा - इसलिए वस्तुएं उम्मीद के अनुसार
निपट

4
ध्यान रखें कि आपके द्वारा scope.Complete()दिए गए नमूने के साथ आपकी कॉल कभी भी हिट नहीं होगी, इसलिए आप लेनदेन हमेशा रोलबैक करेंगे।
एंडी

या न करें usingकी dispose()कहा जाता है, तुम वापस कब, इस युक्त समारोह usingब्लॉक वापस आ गए और यह से संबंधित सब कुछ अनाथ कर दिया जाएगा। इसलिए, भले ही scope"द्वारा" का निपटान नहीं किया गया हो using(यह होगा, जैसा कि अन्य ने समझाया) इसे वैसे भी निपटाया जाएगा क्योंकि फ़ंक्शन समाप्त हो गया। यदि C # का gotoकथन था -तो क्या आपने अभी तक हंसी-मजाक किया है? अच्छा- फिर वापसी के बजाय आप gotoबंद कंस के बाद लौट सकते हैं , बिना वापस लौटे। तार्किक रूप से, scopeअभी भी निपटाया जाएगा, लेकिन आपने gotoसी # में रखा है , इसलिए उस स्तर पर तर्क की परवाह कौन करता है।
शानदार


जवाबों:


145

यह returnआपके usingब्लॉक के अंदर कॉल करने के लिए पूरी तरह से सुरक्षित है , क्योंकि एक ब्लॉक का उपयोग सिर्फ एक try/finallyब्लॉक है।

वापसी के बाद ऊपर दिए गए आपके उदाहरण में true, स्कोप का निपटान हो जाएगा और मान वापस आ जाएगा। return false, और बुलाया नहींscope.Complete() जाएगा । हालाँकि इसे तब तक परवाह नहीं कहा जाएगा क्योंकि यह अंततः ब्लॉक के अंदर रहता है।Dispose

आपका कोड अनिवार्य रूप से इस के समान है (यदि यह समझना आसान हो जाता है):

var scope = new TransactionScope())
try
{
  // my core logic
  return true; // if condition met else
  return false;
  scope.Complete();
}
finally
{
  if( scope != null) 
    ((IDisposable)scope).Dispose();
}

कृपया ध्यान रखें कि आपका लेनदेन कभी भी प्रतिबद्ध नहीं होगा क्योंकि लेनदेन करने के लिए कोई रास्ता नहीं है scope.Complete()


13
आपको यह स्पष्ट करना चाहिए कि Dispose क्या कहा जाएगा । यदि ओपी को पता नहीं है कि क्या होता है using, तो संभावना है कि वह नहीं जानता कि क्या होता है finally
कोनराड रुडोल्फ

रिटर्न के साथ एक यूज़िंग
thewhiteambit

मेरे अनुभव में, यह SQL सर्वर CLR असेंबली के साथ काम नहीं करता है। जब मुझे एक UDF के लिए परिणाम वापस करने की आवश्यकता होती है जिसमें एक SqlXml फ़ील्ड होती है जो एक मेमोरीस्ट्रीम ऑब्जेक्ट को संदर्भित कर रही है। मुझे " एक डिस्पोज़्ड ऑब्जेक्ट एक्सेस नहीं कर सकता " और " कॉल करने का अमान्य प्रयास पढ़ें जब स्ट्रीम बंद हो जाए। ", इसलिए मुझे लीक कोड लिखने और इस परिदृश्य में उपयोग-कथन को वापस लेने के लिए बाध्य किया गया है। :( मेरी एकमात्र आशा है कि SQL सीएलआर इन वस्तुओं के निपटान को संभाल लेगा। यह एक अनूठा परिदृश्य है, लेकिन मैंने सोचा था कि मैं साझा करूँगा।
माइकटीवाई

1
@MikeTeeVee - क्लीनर समाधान या तो (ए) के पास कॉल करने वाले हैं using, जैसे using (var callersVar = MyFunc(..)) .., "MyFunc" का उपयोग करने के बजाय - मेरा मतलब है कि कॉलर को स्ट्रीम दिया गया है और यह usingस्पष्ट रूप से या स्पष्ट रूप से बंद करने के लिए जिम्मेदार है , या (बी) MyFunc निकालने के लिए जो भी जानकारी अन्य वस्तुओं में आवश्यक है, वह सुरक्षित रूप से वापस पारित की जा सकती है - फिर अंतर्निहित डेटा ऑब्जेक्ट या स्ट्रीम आपके द्वारा निपटाए जा सकते हैं using। आपको लीक से हटकर कोड नहीं लिखना चाहिए।
टूलमेकरसेव

6

यह ठीक है - finallyक्लॉज़ (जो कि क्लॉस के क्लोज़िंग कर्ली ब्रेस usingको हुड के नीचे करता है) हमेशा स्कोप को छोड़ दिया जाता है, जब कोई गुंजाइश नहीं होती है, तो कोई बात नहीं।

हालाँकि, यह केवल उन कथनों के लिए सही है जो अंततः ब्लॉक में हैं (जिनका उपयोग करते समय स्पष्ट रूप से सेट नहीं किया जा सकता है using)। इसलिए, आपके उदाहरण में, scope.Complete()कभी भी कॉल नहीं किया जाएगा (मुझे उम्मीद है कि संकलक आपको अगम्य कोड के बारे में चेतावनी दे सकता है)।


2

सामान्य तौर पर, यह एक अच्छा तरीका है। लेकिन आपके मामले में, यदि आप कॉल करने से पहले लौटते हैं, तो scope.Complete()यह सिर्फ TransactionScope को मिटा देगा। अपने डिजाइन पर निर्भर करता है।

तो, इस नमूने में, पूर्ण () नहीं कहा जाता है, और स्कोप का निपटारा किया जाता है, यह मानते हुए कि यह आईडीआईसोपोलेटरी इंटरफ़ेस विरासत में मिला है।


यह आईडीआईओएसपी को लागू करना चाहिए या अभ्यस्त संकलन का उपयोग नहीं करना चाहिए।
12ey पर क्रिसयेर2000

2

गुंजाइश है return। पूरा निश्चित रूप से पहले बुलाया जाना चाहिए । कंपाइलर एक चेतावनी प्रदर्शित करेगा और यह कोड कभी नहीं कहा जाएगा।

returnअपने बारे में - हां, इसे usingबयान के अंदर कहना सुरक्षित है । उपयोग करने का अनुवाद करने की कोशिश की जाती है, अंत में दृश्य के पीछे ब्लॉक करना और अंत में ब्लॉक को निश्चित रूप से निष्पादित किया जाना है।


1

आपके द्वारा दिए गए उदाहरण में, एक समस्या है; scope.Complete()कभी नहीं कहा जाता है। दूसरे, returnबयानों के अंदर usingबयान का इस्तेमाल करना अच्छी बात नहीं है । निम्नलिखित का संदर्भ लें:

using(var scope = new TransactionScope())
{
    //have some logic here
    return scope;      
}

इस सरल उदाहरण में, मुद्दा यह है कि; scopeकथन का उपयोग समाप्त होने पर वसीयत का मूल्य शून्य हो जाएगा।

इसलिए बयानों का उपयोग करके अंदर नहीं लौटना बेहतर है।


1
सिर्फ इसलिए कि 'रिटर्न स्कोप' व्यर्थ है, इसका मतलब यह नहीं है कि रिटर्न स्टेटमेंट गलत है।
प्रीतसंघ

सिर्फ इसलिए कि सर्वोत्तम प्रथाओं का उपयोग न करने का अर्थ यह नहीं है कि आपने कुछ गलत किया है। इसका तात्पर्य, बचने के लिए सबसे अच्छा है, क्योंकि इससे अप्रत्याशित परिणाम हो सकते हैं।
daryal

1
का मान scopeशून्य नहीं होगा - केवल एक चीज जो हुई होगी Dispose()वह उस उदाहरण पर लागू की गई होगी, और इसलिए उदाहरण का अब उपयोग नहीं किया जाना चाहिए (लेकिन यह अशक्त नहीं है और आपको प्रयास करने और उपयोग करने से रोकने के लिए कुछ भी नहीं है। डिस्पोज़्ड ऑब्जेक्ट, भले ही यह वास्तव में एक डिस्पोजेबल ऑब्जेक्ट का अनुचित उपयोग हो)।
लुसिरो

ल्यूकोरो काफी सही है। डिस्पोज़ किए जाने के बाद डिस्पोजेबल ऑब्जेक्ट्स शून्य नहीं हैं। इसकी IsDisposed संपत्ति सत्य है, लेकिन यदि आप अशक्त के खिलाफ जांच करते हैं तो आप झूठे हो जाते हैं और उस वस्तु का return scopeसंदर्भ देते हैं । इस तरह, यदि आप रिटर्न पर उस संदर्भ को असाइन करते हैं तो आप जीसी को निपटाने वाली वस्तु को साफ करने से रोकते हैं।
थंडरग्रो

1

यह सुनिश्चित करने के लिए कि scope.Complete()वसीयत को बुलाया जाएगा, इसे लपेटें try/finallydisposeक्योंकि आप के साथ लपेट है कहा जाता है usingएक विकल्प है कि try/finallyब्लॉक।

using(var scope = new TransactionScope())
{
  try
  {
  // my core logic
  return true; // if condition met else
  return false;
  }
  finally
  {
   scope.Complete();
  }
}

मुझे लगता है कि आप कहना चाहते हैं कि क्या आप जीते हैं - यदि आप चाहते हैं, तो नहीं ... आपके कोड के अनुसार नहीं। :)

0

इस उदाहरण में, गुंजाइश। पूर्ण () कभी भी निष्पादित नहीं होगी। हालाँकि, वापसी आदेश स्टैक पर असाइन किया गया सब कुछ साफ़ करेगा। जीसी उन सभी चीजों का ध्यान रखेगा जो अपरिचित हैं। इसलिए, जब तक कि कोई ऐसी वस्तु नहीं है जिसे जीसी द्वारा नहीं उठाया जा सकता है, कोई समस्या नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.