CA2202, इस मामले को कैसे हल किया जाए


102

क्या कोई मुझे बता सकता है कि निम्नलिखित कोड से सभी CA2202 चेतावनियों को कैसे हटाया जाए?

public static byte[] Encrypt(string data, byte[] key, byte[] iv)
{
    using(MemoryStream memoryStream = new MemoryStream())
    {
        using (DESCryptoServiceProvider cryptograph = new DESCryptoServiceProvider())
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptograph.CreateEncryptor(key, iv), CryptoStreamMode.Write))
            {
                using(StreamWriter streamWriter = new StreamWriter(cryptoStream))
                {
                    streamWriter.Write(data);
                }
            }
        }
        return memoryStream.ToArray();
    }
}

चेतावनी 7 CA2202: Microsoft.Usage: ऑब्जेक्ट 'cryptoStream' विधि 'CryptoServices.Encrypt (स्ट्रिंग, बाइट [], बाइट [])' में एक से अधिक बार निपटाया जा सकता है। System.ObjectDisposedException उत्पन्न करने से बचने के लिए आपको किसी ऑब्जेक्ट पर एक से अधिक बार डिस्पोज़ नहीं करना चाहिए। लाइनें: 34

चेतावनी 8 CA2202: Microsoft.Usage: ऑब्जेक्ट 'मैमोरीस्ट्रीम' को 'CryptoServices.Encrypt (string, byte [], byte [])' विधि में एक से अधिक बार निपटाया जा सकता है। System.ObjectDisposedException उत्पन्न करने से बचने के लिए आपको किसी ऑब्जेक्ट पर एक से अधिक बार डिस्पोज़ नहीं करना चाहिए। लाइन्स: 34, 37

इन चेतावनियों को देखने के लिए आपको विज़ुअल स्टूडियो कोड विश्लेषण की आवश्यकता है (ये c # संकलक चेतावनी नहीं हैं)।


1
यह कोड इन चेतावनियों को उत्पन्न नहीं करता है।
जूलियन होराउ सेप

1
मुझे इसके लिए 0 चेतावनी मिलती है (वार्न स्तर 4, वीएस2010)। और किसी को इस क्षेत्र में समस्याओं का सामना करने के लिए, दलीलों के साथ-साथ चेतावनियों का पाठ भी जोड़ना चाहिए।
हेन्क होल्टरमैन

29
CAxxxx चेतावनियाँ कोड विश्लेषण और FxCop द्वारा उत्पन्न की जाती हैं ।
dtb

यह चेतावनी दिखाए गए कोड पर लागू नहीं होती है - इस परिदृश्य के लिए चेतावनियों को दबाया जा सकता है। एक बार जब आप अपने कोड की समीक्षा कर लेते हैं और उस मूल्यांकन से सहमत हो जाते हैं, तो इसे अपने तरीके से ऊपर रखें: " [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification="BrainSlugs83 said so.")]" - सुनिश्चित करें कि आपके पास using System.Diagnostics.CodeAnalysis;अपने usings ब्लॉक में " " स्टेटमेंट है।
ब्रेनस्ल्गस83

2
पर एक नज़र है: msdn.microsoft.com/en-us/library/…
आदिल

जवाबों:


-3

यह चेतावनी के बिना संकलित करता है:

    public static byte[] Encrypt(string data, byte[] key, byte[] iv)
    {
        MemoryStream memoryStream = null;
        DESCryptoServiceProvider cryptograph = null;
        CryptoStream cryptoStream = null;
        StreamWriter streamWriter = null;
        try
        {
            memoryStream = new MemoryStream();
            cryptograph = new DESCryptoServiceProvider();
            cryptoStream = new CryptoStream(memoryStream, cryptograph.CreateEncryptor(key, iv), CryptoStreamMode.Write);
            var result = memoryStream;              
            memoryStream = null;
            streamWriter = new StreamWriter(cryptoStream);
            cryptoStream = null;
            streamWriter.Write(data);
            return result.ToArray();
        }
        finally
        {
            if (memoryStream != null)
                memoryStream.Dispose();
            if (cryptograph != null)
                cryptograph.Dispose();
            if (cryptoStream != null)
                cryptoStream.Dispose();
            if (streamWriter != null)
                streamWriter.Dispose();
        }
    }

टिप्पणियों के जवाब में संपादित करें : मैंने अभी फिर से सत्यापित किया है कि यह कोड चेतावनी उत्पन्न नहीं करता है, जबकि मूल एक करता है। मूल कोड में, CryptoStream.Dispose()और MemoryStream().Dispose() वास्तव में दो बार कहा जाता है (जो एक समस्या हो सकती है या नहीं)।

संशोधित कोड निम्नानुसार काम करता है: संदर्भ सेट किए जाते हैं null, जैसे ही निपटान के लिए जिम्मेदार वस्तु को किसी अन्य ऑब्जेक्ट में स्थानांतरित किया जाता है। निर्माता को कॉल सफल होने के बाद ईजी memoryStreamसेट किया nullगया है CryptoStream। कन्स्ट्रक्टर को कॉल करने के बाद cryptoStreamसेट किया गया null, जो StreamWriterसफल रहा। यदि कोई अपवाद नहीं होता है, streamWriterतो finallyब्लॉक में निपटाया जाता है और बदले में निपटान होगा CryptoStreamऔर MemoryStream


85
-1-बदसूरत कोड बनाने के लिए यह वास्तव में बुरा है कि एक चेतावनी का पालन करना चाहिए
जोर्डो

4
मैं सहमत हूँ कि आप कसाई को उस चीज़ के लिए कोड नहीं करना चाहिए जो भविष्य में किसी बिंदु पर तय हो सकती है, बस दबा दें।
13

3
यह समस्या का समाधान कैसे करता है? CA2202 अभी भी रिपोर्ट किया गया है क्योंकि मेमोरीस्ट्रीम अभी भी अंततः ब्लॉक में दो बार निपटाया जा सकता है।
क्रिस गेसलर

3
चूंकि CryptoStream आंतरिक रूप से MemoryStream पर Dispose कहती है, इसलिए इसे दो बार कहा जा सकता है, जो चेतावनी का कारण है। मैंने आपके समाधान की कोशिश की और अभी भी चेतावनी प्राप्त कर रहा हूं।
क्रिस गेसलर

2
ओह जीज़, आप सही हैं - मुझे उम्मीद नहीं थी कि आपके लॉजिक-लॉजिक में क्लीन-लॉजिक मिला होगा ... लॉजिक-लॉजिक ... - यह सिर्फ विचित्र और गूढ़ है - यह निश्चित रूप से चतुर है - लेकिन फिर, डरावना - कृपया उत्पादन कोड में ऐसा न करें; स्पष्ट होना: आपको लगता है कि कोई वास्तविक कार्यात्मक मुद्दा नहीं है जो इसे हल कर रहा है, सही है? (इन वस्तुओं को कई बार निपटाना ठीक है।) - अगर मैं कर सकता था तो मैं नीचे के वोट को हटा देता हूं (एसओ मुझे रोकता है, यह कहता है कि आपको उत्तर को संपादित करना होगा) - लेकिन मैं केवल अनिच्छा से ऐसा करूंगा ... - और गंभीरता से, यह कभी मत करो।
BrainSlugs83

142

आपको इस मामले में चेतावनी को दबा देना चाहिए। कोड जो डिस्पोज़ेबल्स के साथ काम करता है, सुसंगत होना चाहिए, और आपको यह ध्यान नहीं रखना चाहिए कि अन्य वर्ग आपके द्वारा बनाए गए डिस्पोज़ेबल्स का स्वामित्व लेते हैं और Disposeउन पर कॉल भी करते हैं।

[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] Encrypt(string data, byte[] key, byte[] iv) {
  using (var memoryStream = new MemoryStream()) {
    using (var cryptograph = new DESCryptoServiceProvider())
    using (var cryptoStream = new CryptoStream(memoryStream, cryptograph.CreateEncryptor(key, iv), CryptoStreamMode.Write))
    using (var streamWriter = new StreamWriter(cryptoStream)) {
      streamWriter.Write(data);
    }
    return memoryStream.ToArray();
  }
}

अद्यतन: में IDisposable.Dispose प्रलेखन आप इस पढ़ सकते हैं:

यदि किसी ऑब्जेक्ट की डिस्पोज़ विधि को एक से अधिक बार कॉल किया जाता है, तो ऑब्जेक्ट को पहले एक के बाद सभी कॉल को अनदेखा करना चाहिए। यदि ऑब्जेक्ट को कई बार कहा जाता है, तो ऑब्जेक्ट को अपवाद नहीं फेंकना चाहिए।

यह तर्क दिया जा सकता है कि यह नियम मौजूद है ताकि डेवलपर्स usingस्टेटमेंट को डिस्पोजेबल के कैस्केड में पूरी तरह से नियोजित कर सकें , जैसे मैंने ऊपर दिखाया है (या शायद यह सिर्फ एक अच्छा साइड-इफेक्ट है)। उसी टोकन से, तब, CA2202 कोई उपयोगी उद्देश्य नहीं देता है, और इसे परियोजना-वार को दबा दिया जाना चाहिए। वास्तविक अपराधी का दोषपूर्ण कार्यान्वयन होगा Dispose, और CA1065 को इस बात का ध्यान रखना चाहिए (यदि यह आपकी जिम्मेदारी के अधीन है)।


14
मेरी राय में यह fxcop में एक बग है, यह नियम केवल गलत है। डिस्पोज़ विधि को एक ObjectDisposedException को कभी नहीं फेंकना चाहिए और यदि ऐसा होता है, तो आपको उस समय कोड के लेखक पर एक बग दर्ज करके उससे निपटना चाहिए जो कि इस तरह से लागू होता है।
justin.m.chase

14
मैं अन्य सूत्र में @HansPassant से सहमत हूं: उपकरण अपना काम कर रहा है और आपको कक्षाओं के अप्रत्याशित कार्यान्वयन विवरण के बारे में चेतावनी दे रहा है। व्यक्तिगत रूप से, मुझे लगता है कि वास्तविक समस्या API का डिज़ाइन है। नेस्टेड क्लासेस को यह मानने के लिए डिफॉल्ट करना कि कहीं और बनाई गई किसी अन्य ऑब्जेक्ट का स्वामित्व लेना ठीक है, अत्यधिक संदिग्ध लगता है। मैं देख सकता हूं कि यदि उपयोगी वस्तु वापस आने वाली थी, तो यह उपयोगी हो सकता है, लेकिन उस धारणा के लिए डिफ़ॉल्ट रूप से काउंटर-सहज ज्ञान युक्त लगता है, साथ ही साथ सामान्य आईडीसोपोर्टर पैटर्न का उल्लंघन भी होता है।
BTJ

8
लेकिन इस प्रकार के संदेश को दबाने के लिए msdn दोबारा नहीं आता है। पर एक नज़र है: msdn.microsoft.com/en-us/library/…
आदिल

2
लिंक @AdilMammadov, उपयोगी जानकारी के लिए धन्यवाद, लेकिन Microsoft हमेशा इन चीजों के बारे में सही नहीं हैं।
टिम अबेल

40

खैर, यह सही है, इन धाराओं पर निपटान () विधि को एक से अधिक बार कहा जाएगा। StreamReader वर्ग cryptoStream का 'स्वामित्व' लेगा, इसलिए स्ट्रीम स्ट्रीम को निपटाना भी CryptoStream को डिस्पोज़ करेगा। इसी तरह, CryptoStream वर्ग मेमोरीस्ट्रीम की जिम्मेदारी लेता है।

ये बिल्कुल वास्तविक बग नहीं हैं, ये .NET क्लास मल्टीपल डिस्पोज () कॉल के लिए लचीला हैं। लेकिन अगर आप चेतावनी से छुटकारा पाना चाहते हैं तो आपको इन वस्तुओं के लिए उपयोग स्टेटमेंट को छोड़ देना चाहिए। और जब कोड एक अपवाद फेंकता है तो क्या होगा यह तर्क देते समय अपने आप को थोड़ा दर्द दें। या एक विशेषता के साथ चेतावनी को शट-अप करें। या सिर्फ चेतावनी को नजरअंदाज करें क्योंकि यह मूर्खतापूर्ण है।


10
कक्षाओं के आंतरिक व्यवहार के बारे में विशेष ज्ञान रखने के लिए (जैसे एक दूसरे का एक डिस्पोजेबल स्वामित्व), यह पूछने के लिए बहुत अधिक है कि क्या कोई पुन: प्रयोज्य एपीआई डिजाइन करना चाहता है। इसलिए मुझे लगता है कि usingबयानों को रुकना चाहिए। ये चेतावनी वाकई मूर्खतापूर्ण है।
जोर्डो

4
@ जोर्डो - क्या यह उपकरण के लिए नहीं है? आपको आंतरिक व्यवहार के बारे में चेतावनी देने के लिए जिसके बारे में आप नहीं जानते होंगे?
हंस पासेंट

8
मैं सहमत हूँ। लेकिन, मैं अभी भी usingबयान नहीं छोड़ूंगा । किसी वस्तु के निपटान के लिए किसी अन्य वस्तु पर निर्भर होना गलत है। इस कोड के लिए, यह ठीक है, लेकिन वहाँ Streamऔर TextWriterबाहर (बीसीएल पर न केवल) के कई कार्यान्वयन हैं । उन सभी का उपयोग करने के लिए कोड सुसंगत होना चाहिए।
जोर्डो

3
हां, जोर्डो से सहमत हैं। यदि आप वास्तव में चाहते हैं कि प्रोग्रामर एपी के आंतरिक व्यवहार से अवगत है, तो अपने फ़ंक्शन को DoSomethingAndDisposeStream (स्ट्रीम स्ट्रीम, अन्य डेटा) के रूप में नाम देकर बोलें।
ZZZ

4
@HansPassant क्या आप यह बता सकते हैं कि यह कहाँ से प्रलेखित है जो XmlDocument.Save()विधि Disposeप्रदत्त पैरामीटर पर कॉल करेगा ? मैं इसे Save(XmlWriter)(जहाँ मैं FxCop बग का अनुभव कर रहा हूँ) Save()के प्रलेखन में, या विधि में या स्वयं के प्रलेखन में नहीं देखता हूँ XmlDocument
इयान बोयड

9

जब एक StreamWriter का निपटान किया जाता है, तो यह स्वचालित रूप से लिपटे स्ट्रीम (यहाँ: CryptoStream ) का निपटान करेगा । CryptoStream भी लिपटे स्ट्रीम को स्वचालित रूप से हटा देता है (यहाँ: MemoryStream )।

तो अपने MemoryStream द्वारा दोनों निपटान किया जाता है CryptoStream और का उपयोग कर बयान। और आपका CryptoStream StreamWriter और बाहरी स्टेटमेंट का उपयोग करके निपटाया जाता है ।


कुछ प्रयोग के बाद, चेतावनी से पूरी तरह से छुटकारा पाना असंभव प्रतीत होता है। सैद्धांतिक रूप से, मेमोरीस्ट्रीम को निपटाया जाना आवश्यक है, लेकिन तब आप सैद्धांतिक रूप से अपनी ToArray विधि का उपयोग नहीं कर सकते। व्यावहारिक रूप से, एक मेमोरीस्ट्रीम को निपटाने की आवश्यकता नहीं है, इसलिए मैं इस समाधान के साथ जाऊंगा और CA2000 चेतावनी को दबाऊंगा।

var memoryStream = new MemoryStream();

using (var cryptograph = new DESCryptoServiceProvider())
using (var writer = new StreamWriter(new CryptoStream(memoryStream, ...)))
{
    writer.Write(data);
}

return memoryStream.ToArray();

9

मैं यह प्रयोग करूँगा #pragma warning disable

.NET फ्रेमवर्क दिशानिर्देश IDis प्रयोज्य को लागू करने की सलाह देते हैं। इस तरह से प्रस्तावित करें कि इसे कई बार कहा जा सके। से IDisposable.Dispose की MSDN विवरण :

यदि ऑब्जेक्ट को एक से अधिक बार कहा जाता है, तो ऑब्जेक्ट को अपवाद नहीं फेंकना चाहिए

इसलिए चेतावनी लगभग निरर्थक लगती है:

System.ObjectDisposedException उत्पन्न करने से बचने के लिए आपको किसी ऑब्जेक्ट पर एक से अधिक बार डिस्पोज़ नहीं करना चाहिए

मुझे लगता है कि यह तर्क दिया जा सकता है कि चेतावनी मददगार हो सकती है यदि आप एक बुरी तरह से कार्यान्वित किए गए आईडीआईसॉपी वस्तु का उपयोग कर रहे हैं जो मानक कार्यान्वयन दिशानिर्देशों का पालन नहीं करता है। लेकिन जब आप जैसे .NET फ्रेमवर्क से कक्षाओं का उपयोग करते हैं, तो मैं कहूंगा कि #pragma का उपयोग करके चेतावनी को दबा देना सुरक्षित है। और IMHO इस चेतावनी के लिए MSDN प्रलेखन में सुझाए गए हुप्स से गुजरना बेहतर है ।


4
CA2202 एक कोड विश्लेषण चेतावनी है और संकलक चेतावनी नहीं है। #pragma warning disableकेवल संकलक चेतावनी को दबाने के लिए इस्तेमाल किया जा सकता है। एक कोड विश्लेषण चेतावनी को दबाने के लिए आपको एक विशेषता का उपयोग करने की आवश्यकता है।
मार्टिन लीवरेज

2

मुझे अपने कोड में इसी तरह के मुद्दों का सामना करना पड़ा।

ऐसा लगता है कि पूरी तरह से CA2202 चीज़ ट्रिगर हो गई है क्योंकि MemoryStreamयदि कंस्ट्रक्टर (CA2000) में अपवाद होता है, तो इसका निपटान किया जा सकता है।

इसे इस तरह हल किया जा सकता है:

 1 public static byte[] Encrypt(string data, byte[] key, byte[] iv)
 2 {
 3    MemoryStream memoryStream = GetMemoryStream();
 4    using (DESCryptoServiceProvider cryptograph = new DESCryptoServiceProvider())
 5    {
 6        CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptograph.CreateEncryptor(key, iv), CryptoStreamMode.Write);
 7        using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
 8        {
 9            streamWriter.Write(data);
10            return memoryStream.ToArray();
11        }
12    }
13 }
14
15 /// <summary>
16 /// Gets the memory stream.
17 /// </summary>
18 /// <returns>A new memory stream</returns>
19 private static MemoryStream GetMemoryStream()
20 {
21     MemoryStream stream;
22     MemoryStream tempStream = null;
23     try
24     {
25         tempStream = new MemoryStream();
26
27         stream = tempStream;
28         tempStream = null;
29     }
30     finally
31     {
32         if (tempStream != null)
33             tempStream.Dispose();
34     }
35     return stream;
36 }

ध्यान दें कि हमें memoryStreamअंतिम usingकथन (लाइन 10) के अंदर वापस लौटना है क्योंकि cryptoStreamलाइन 11 पर निपटाया जाता है (क्योंकि इसका उपयोग streamWriter usingस्टेटमेंट में किया जाता है ), जिसके कारण memoryStreamलाइन 11 पर भी निस्तारण हो जाता है (क्योंकि memoryStreamइसका उपयोग करने के लिए किया जाता है cryptoStream)।

कम से कम इस कोड ने मेरे लिए काम किया।

संपादित करें:

अजीब लग सकता है क्योंकि मुझे पता चला है कि यदि आप GetMemoryStreamविधि को निम्न कोड से बदलते हैं ,

/// <summary>
/// Gets a memory stream.
/// </summary>
/// <returns>A new memory stream</returns>
private static MemoryStream GetMemoryStream()
{
    return new MemoryStream();
}

आपको वही परिणाम मिलता है।


1

क्रिप्टोस्ट्रीम मेमोरीस्ट्रीम पर आधारित है।

जो प्रतीत हो रहा है वह यह है कि जब क्रायपोस्ट्रीम का उपयोग किया जाता है (अंत में) मेमोरीस्ट्रीम को भी डिस्पोज किया जाता है, तो मेमोरीस्ट्रीम को फिर से डिस्पोज किया जाता है।


1

मैं इसे सही तरीके से हल करना चाहता था - जो कि चेतावनियों को दबाए बिना और सभी डिस्पोजेबल वस्तुओं को सही तरीके से निपटाने के बिना है।

मैंने 3 में से 2 धाराओं को खेतों के रूप में निकाला और उन्हें Dispose()अपनी कक्षा की विधि में निपटाया । हां, IDisposableइंटरफ़ेस को लागू करना जरूरी नहीं है कि आप क्या देख रहे हैं, लेकिन dispose()कोड में सभी यादृच्छिक स्थानों से कॉल की तुलना में समाधान बहुत साफ दिखता है ।

public class SomeEncryption : IDisposable
    {
        private MemoryStream memoryStream;

        private CryptoStream cryptoStream;

        public static byte[] Encrypt(string data, byte[] key, byte[] iv)
        {
             // Do something
             this.memoryStream = new MemoryStream();
             this.cryptoStream = new CryptoStream(this.memoryStream, encryptor, CryptoStreamMode.Write);
             using (var streamWriter = new StreamWriter(this.cryptoStream))
             {
                 streamWriter.Write(plaintext);
             }
            return memoryStream.ToArray();
        }

       public void Dispose()
        { 
             this.Dispose(true);
             GC.SuppressFinalize(this);
        }

       protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.memoryStream != null)
                {
                    this.memoryStream.Dispose();
                }

                if (this.cryptoStream != null)
                {
                    this.cryptoStream.Dispose();
                }
            }
        }
   }

0

ऑफ-टॉपिक लेकिन मैं आपको समूहीकरण के लिए एक अलग प्रारूपण तकनीक का उपयोग करने का सुझाव दूंगा using:

using (var memoryStream = new MemoryStream())
{
    using (var cryptograph = new DESCryptoServiceProvider())
    using (var encryptor = cryptograph.CreateEncryptor(key, iv))
    using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
    using (var streamWriter = new StreamWriter(cryptoStream))
    {
        streamWriter.Write(data);
    }

    return memoryStream.ToArray();
}

मैं भी varवास्तव में लंबे वर्ग के नाम की पुनरावृत्ति से बचने के लिए यहां का उपयोग करने की वकालत करता हूं ।

पुनश्च ओर इशारा करते हुए मुझे नहीं पहले के लिए न आना ब्रेसिज़ कर सकते हैं के लिए @ShellShock के लिए धन्यवाद usingयह होगा के रूप में memoryStreamमें returnक्षेत्र से बाहर बयान।


5
नहीं होगा।
पॉलीफ़न

यह कोड के मूल टुकड़े के बिल्कुल बराबर है। मैंने सिर्फ घुंघराले ब्रेसिज़ उतारे हैं, बहुत कुछ जैसे आप ifएस के साथ कर सकते हैं (हालांकि मैं इस तकनीक को usingएस के अलावा किसी भी चीज़ के लिए सलाह नहीं दूंगा )।
दान अब्रामोव

2
मूल कोड में, memoryStream.ToArray () पहले उपयोग के दायरे के अंदर था; आप इसे दायरे से बाहर कर चुके हैं।
पॉलीफ़ुन

बहुत बहुत धन्यवाद, मैं सिर्फ एहसास हुआ कि आप returnबयान का मतलब है। सच है। मैंने इसे प्रतिबिंबित करने के लिए उत्तर संपादित किया।
दान अब्रामोव

मैं व्यक्तिगत रूप से लगता है कि usingबिना ब्रेसिज़ कोड को अधिक नाजुक बनाता है (विचार वर्षों के अंतर और विलय)। joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong & imperialviolet.org/2014/02/22/applebug.html
टिम एबेल

0

सभी usings से बचें और नेस्टेड डिस्पोज़-कॉल का उपयोग करें!

    public static byte[] Encrypt(string data, byte[] key, byte[] iv)
    {
        MemoryStream memoryStream = null;
        DESCryptoServiceProvider cryptograph = null;
        CryptoStream cryptoStream = null;
        StreamWriter streamWriter = null;

        try
        {
            memoryStream = new MemoryStream();
            cryptograph = new DESCryptoServiceProvider();
            cryptoStream = new CryptoStream(memoryStream, cryptograph.CreateEncryptor(key, iv), CryptoStreamMode.Write);
            streamWriter = new StreamWriter(cryptoStream);

            streamWriter.Write(data);
            return memoryStream.ToArray();
        }
        finally 
        {
            if(streamWriter != null)
                streamWriter.Dispose();
            else if(cryptoStream != null)
                cryptoStream.Dispose();
            else if(memoryStream != null)
                memoryStream.Dispose();

            if (cryptograph != null)
                cryptograph.Dispose();
        }
    }

1
कृपया बताएं कि आपको usingइस मामले में क्यों बचना चाहिए ।
स्टुपरयूसर

1
आप उपयोग-कथन को बीच में रख सकते हैं, लेकिन आपको दूसरे को हल करना होगा। एक तार्किक सुसंगत और सभी दिशाओं में अपग्रेड करने योग्य समाधान प्राप्त करने के लिए मैंने सभी उपयोगों को हटाने का फैसला किया!
हैरी साल्ट्ज़मैन

0

मैं सिर्फ कोड को खोलना चाहता था ताकि हम Disposeवस्तुओं पर कई कॉल देख सकें :

memoryStream = new MemoryStream()
cryptograph = new DESCryptoServiceProvider()
cryptoStream = new CryptoStream()
streamWriter = new StreamWriter()

memoryStream.Dispose(); //implicitly owned by cryptoStream
cryptoStream.Dispose(); //implicitly owned by streamWriter
streamWriter.Dispose(); //through a using

cryptoStream.Dispose(); //INVALID: second dispose through using
cryptograph.Dispose(); //through a using
memorySTream.Dipose(); //INVALID: second dispose through a using

return memoryStream.ToArray(); //INVALID: accessing disposed memoryStream

जबकि अधिकांश .NET क्लास (बहुतायत से) कॉल करने की गलती के खिलाफ लचीला हैं .Dispose, लेकिन सभी वर्ग प्रोग्रामर के दुरुपयोग के खिलाफ रक्षात्मक नहीं हैं।

एफएक्स कॉप यह जानता है, और आपको चेतावनी देता है।

आपके पास कुछ विकल्प हैं;

  • Disposeकिसी भी वस्तु पर केवल एक बार कॉल करें ; उपयोग न करेंusing
  • दो बार कॉल डिस्पोज़ करते रहें, और उम्मीद करें कि कोड क्रैश न हो
  • चेतावनी को दबाएं

-1

मैंने इस तरह के कोड का उपयोग किया था जो बाइट लेता है [] और बाइट को वापस करता है [] स्ट्रीम्स का उपयोग किए बिना

public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
  DES des = new DES();
  des.BlockSize = 128;
  des.Mode = CipherMode.CBC;
  des.Padding = PaddingMode.Zeros;
  des.IV = IV
  des.Key = key
  ICryptoTransform encryptor = des.CreateEncryptor();

  //and finaly operations on bytes[] insted of streams
  return encryptor.TransformFinalBlock(plaintextarray,0,plaintextarray.Length);
}

इस तरह से आपको एनकोडिंग का उपयोग करके स्ट्रिंग से बाइट [] तक रूपांतरण करना होगा।

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