2011-12-26 11 views
7

एफ # कोड निम्न चेतावनी मेंएफ # में रिकर्सिव ऑब्जेक्ट्स?

let rec reformat = new EventHandler(fun _ _ -> 
     b.TextChanged.RemoveHandler reformat 
     b |> ScrollParser.rewrite_contents_of_rtb 
     b.TextChanged.AddHandler reformat 
     ) 
    b.TextChanged.AddHandler reformat 

परिणामों का यह टुकड़ा:

traynote.fs (62,41): चेतावनी FS0040: यह और वस्तु (रों) किया जा रहा करने के लिए अन्य पुनरावर्ती संदर्भ देरी संदर्भ के उपयोग के माध्यम से परिभाषित रनटाइम पर प्रारंभिकता के लिए परिभाषित किया जाएगा। ऐसा इसलिए है क्योंकि आप पुनरावर्ती कार्यों की बजाय एक या अधिक रिकर्सिव ऑब्जेक्ट्स को परिभाषित कर रहे हैं। इस चेतावनी को '#nowarn "40" या' --nowarn: 40 'का उपयोग करके दबाया जा सकता है।

क्या कोई तरीका है जिसमें इस चेतावनी से बचने के लिए कोड को फिर से लिखा जा सकता है? या एफ # में रिकर्सिव ऑब्जेक्ट्स रखने का कोई कोशर तरीका नहीं है?

उत्तर

14

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

एक उदाहरण है जहां चेतावनी वास्तव में एक समस्या से पता चलता देने के लिए, आप निम्न कोड की कोशिश कर सकते हैं:

type Evil(f) = 
    let n = f() 
    member x.N = n + 1 

let rec e = Evil(fun() -> 
    printfn "%d" (e:Evil).N; 1) 

Evil वर्ग एक निर्माता में एक समारोह लेता है और निर्माण दौरान यह कहता है। नतीजतन, लैम्ब्डा फ़ंक्शन में रिकर्सिव संदर्भ किसी मान पर सेट होने से पहले e तक पहुंचने का प्रयास करता है (और आपको रनटाइम त्रुटि मिल जाएगी)। हालांकि, विशेष रूप से जब ईवेंट हैंडलर के साथ काम करते हैं, तो यह कोई मुद्दा नहीं है (और जब आप रिकर्सिव ऑब्जेक्ट्स का सही उपयोग कर रहे हों तो आपको चेतावनी मिलती है)।

आप चेतावनी से छुटकारा पाने के लिए चाहते हैं, तो आप स्पष्ट ref मानों का उपयोग और null का उपयोग कर कोड को फिर से लिखने सकता है, लेकिन फिर आप एक रनटाइम त्रुटि का एक ही खतरे में हो जाएगा, बस बिना किसी चेतावनी के और भद्दा कोड के साथ :

let foo (evt:IEvent<_, _>) = 
    let eh = ref null 
    eh := new EventHandler(fun _ _ -> 
    evt.RemoveHandler(!eh)) 
    evt.AddHandler(!eh) 
संबंधित मुद्दे