2012-05-16 16 views
12

प्रोजेक्ट का उपयोग करने वाली परियोजना में एकल बेस क्लास से विरासत में बहुत से वर्ग शामिल हैं। यूनिट परीक्षणों में मुझे प्राप्त परिणामों की तुलना प्रकार और डेटा से करने की आवश्यकता है।एफ # कंपाइलर आउटऑफमेमरी एक्सेप्शन

जब मैं मैच का उपयोग करता हूं तो मामले की तुलना में जब स्थिति सूची में कई अलग-अलग स्थितियों के बारे में बताया जाता है तो संकलक OutOfMemoryException फेंकता है।

उदाहरण के लिए, एफ # कोड निम्नलिखित संकलन के दौरान System.OutOfMemoryException (पैरामीटर त्रुटि FS0193) को जन्म देती है (और संकलन के बारे में 30 सेकंड से पहले अपवाद उत्पन्न हुआ था ले लिया)

type IBaseClass() = class end 

type IChildClass1() = inherit IBaseClass() 

type IChildClass2() = inherit IBaseClass() 

type IChildClass3() = inherit IBaseClass() 

type IChildClass4() = inherit IBaseClass() 

type IChildClass5() = inherit IBaseClass() 

type IChildClass6() = inherit IBaseClass() 

type IChildClass7() = inherit IBaseClass() 

type IChildClass8() = inherit IBaseClass() 

type IChildClass9() = inherit IBaseClass() 

type IChildClass10() = inherit IBaseClass() 

type IChildClass11() = inherit IBaseClass() 

type IChildClass12() = inherit IBaseClass() 

type IChildClass13() = inherit IBaseClass() 

type IChildClass14() = inherit IBaseClass() 

type IChildClass15() = inherit IBaseClass() 

type IChildClass16() = inherit IBaseClass() 

type IChildClass17() = inherit IBaseClass() 

type IChildClass18() = inherit IBaseClass() 

type IChildClass19() = inherit IBaseClass() 

type IChildClass20() = inherit IBaseClass() 


let AreEqual (original: IBaseClass) (compareWith: IBaseClass) : bool = 
    match (original, compareWith) with 
    | (:? IChildClass1 as a), (:? IChildClass1 as b) -> a = b 
    | (:? IChildClass2 as a), (:? IChildClass2 as b) -> a = b 
    | (:? IChildClass3 as a), (:? IChildClass3 as b) -> a = b 
    | (:? IChildClass4 as a), (:? IChildClass4 as b) -> a = b 
    | (:? IChildClass5 as a), (:? IChildClass5 as b) -> a = b 
    | (:? IChildClass6 as a), (:? IChildClass6 as b) -> a = b 
    | (:? IChildClass7 as a), (:? IChildClass7 as b) -> a = b 
    | (:? IChildClass8 as a), (:? IChildClass8 as b) -> a = b 
    | (:? IChildClass9 as a), (:? IChildClass9 as b) -> a = b 
    | (:? IChildClass10 as a), (:? IChildClass10 as b) -> a = b 
    | (:? IChildClass11 as a), (:? IChildClass11 as b) -> a = b 
    | (:? IChildClass12 as a), (:? IChildClass12 as b) -> a = b 
    | (:? IChildClass13 as a), (:? IChildClass13 as b) -> a = b 
    | (:? IChildClass14 as a), (:? IChildClass14 as b) -> a = b 
    | (:? IChildClass15 as a), (:? IChildClass15 as b) -> a = b 
    | (:? IChildClass16 as a), (:? IChildClass16 as b) -> a = b 
    | (:? IChildClass17 as a), (:? IChildClass17 as b) -> a = b 
    | (:? IChildClass18 as a), (:? IChildClass18 as b) -> a = b 
    | (:? IChildClass19 as a), (:? IChildClass19 as b) -> a = b 
    | (:? IChildClass20 as a), (:? IChildClass20 as b) -> a = b 
    | _ -> false 

मैं करने के लिए IEquatable इंटरफेस जोड़ सकते हैं यकीन है कि के लिए मेरी IBaseClass वर्ग है कि इस तरह के मैच निर्माण के उपयोग से बचने जाएगा, या IBaseClass इंटरफ़ेस में जोड़ने पूर्णांक तरह सदस्य (या enum) और प्रकार से नहीं मैच करते हैं, लेकिन कुछ लोगों द्वारा int मूल्य

ध्यान दें, मैं एमएस VS 2010 और MSVS 11 बीटा में एक ही परियोजना को संकलित करने की कोशिश की है, और एक ही संकलक त्रुटि

प्रश्न था: क्यों संकलक के OutOfMemoryException मेरे मामले में होता है (यह ज्ञात है संकलक बग या अन्य सीमा), मुझे अपने मैच स्थिति से बचने के लिए कैसे पुनर्गठित करना चाहिए?

अद्यतन जब मैं भेदभाव यूनियनों में कक्षाएं रख दिया और समान मिलान का उपयोग करके तुलना Fsc.exe बिना किसी अपवाद के परियोजना संकलित

type AllClasses = 
    | ChildClass1 of IChildClass1 | ChildClass2 of IChildClass2 | ChildClass3 of IChildClass3 | ChildClass4 of IChildClass4 | ChildClass5 of IChildClass5 | ChildClass6 of IChildClass6 
    | ChildClass7 of IChildClass7 | ChildClass8 of IChildClass8 | ChildClass9 of IChildClass9 | ChildClass10 of IChildClass10 | ChildClass11 of IChildClass11 | ChildClass12 of IChildClass12 
    | ChildClass13 of IChildClass13 | ChildClass14 of IChildClass14 | ChildClass15 of IChildClass15 | ChildClass16 of IChildClass16 | ChildClass17 of IChildClass17 | ChildClass18 of IChildClass18 
    | ChildClass19 of IChildClass19 | ChildClass20 of IChildClass20 

let AreEqual2 (original: AllClasses) (compareWith: AllClasses) : bool = 
    match (original, compareWith) with 
    | ChildClass1(a), ChildClass1(b) -> a = b 
    | ChildClass2(a), ChildClass2(b) -> a = b 
    | ChildClass3(a), ChildClass3(b) -> a = b 
    | ChildClass4(a), ChildClass4(b) -> a = b 
    | ChildClass5(a), ChildClass5(b) -> a = b 
    | ChildClass6(a), ChildClass6(b) -> a = b 
    | ChildClass7(a), ChildClass7(b) -> a = b 
    | ChildClass8(a), ChildClass8(b) -> a = b 
    | ChildClass9(a), ChildClass9(b) -> a = b 
    | ChildClass10(a), ChildClass10(b) -> a = b 
    | ChildClass11(a), ChildClass11(b) -> a = b 
    | ChildClass12(a), ChildClass12(b) -> a = b 
    | ChildClass13(a), ChildClass13(b) -> a = b 
    | ChildClass14(a), ChildClass14(b) -> a = b 
    | ChildClass15(a), ChildClass15(b) -> a = b 
    | ChildClass16(a), ChildClass16(b) -> a = b 
    | ChildClass17(a), ChildClass17(b) -> a = b 
    | ChildClass18(a), ChildClass18(b) -> a = b 
    | ChildClass19(a), ChildClass19(b) -> a = b 
    | ChildClass20(a), ChildClass20(b) -> a = b 
    | _ -> false 

धन्यवाद

+0

मुझे लगता है कि आप केवल चित्रण उद्देश्यों के लिए 'IChildClass1-20' का उपयोग कर रहे हैं, या यह वास्तविक कोड है? मुझे नहीं लगता कि संकलक को कभी भी 'आउटऑफमेमरी अपवाद' फेंकना चाहिए (लेकिन मेरे पास जवाब नहीं है) – Abel

+0

@Abel - हाँ, कक्षा के नाम केवल चित्रण उद्देश्य के लिए हैं, निश्चित रूप से कक्षाओं के अलग-अलग नाम हैं। मेरी मशीन पर ध्यान दें यदि मैं * AreEqual * में IChildClass1-18 का उपयोग करता हूं - प्रोजेक्ट संकलित करने योग्य है, 1 9 और अधिक - बूम ...अपवाद – Vitaliy

उत्तर

9

यह कैसे एफ # संकलक के कारण होता है इस मामले में tuples पर पैटर्न मिलान संकलित करता है। मुझे पूरी तरह से यकीन नहीं है कि जब आप इस विशेष समस्या में वास्तव में दौड़ते हैं और जब संकलक अन्य दृष्टिकोण का उपयोग करता है, लेकिन यहां एक स्पष्टीकरण है कि यह इस मामले में क्यों विफल रहता है ...

यदि आप एक जैसा मिलान करते हैं आपका उदाहरण, कंपाइलर अनिवार्य रूप से एक निर्णय पेड़ उत्पन्न करता है जो original (:? IChildClass1) के लिए पहले पैटर्न का परीक्षण करता है और फिर दो शाखाएं उत्पन्न करता है। पहली शाखा जांचती है कि compareWith भी IChildClass1 है। यदि हां, तो यह पहला मामला चलाता है। पैटर्न मिलान के बाकी तो शाखाओं में से दोनों में दोहराया गया है, तो आप की तरह कुछ (आप ILSpy का उपयोग कर मामलों की छोटी संख्या के लिए संकलित कोड को देखकर यह जांच कर सकते हैं) मिलती है:

if (original is IChildClass1) 
    if (compareWith is IChildClass1) 
    case #1 
    if (original is IChildClass2) 
    if (compareWith is IChildClass2) 
     case #2 
    if (original is IChildClass3) 
     (...) 
else 
    if (original is IChildClass2) 
    if (compareWith is IChildClass2) 
     case #2 
    if (original is IChildClass3) 
     (...) 

यह इसका मतलब है कि जेनरेट कोड का आकार इस पैटर्न मिलान में मामलों की संख्या के लिए आनुपातिक रूप से आनुपातिक है। 20 मामलों के लिए, कंपाइलर 2^20 शाखाएं बनाने की कोशिश करता है, जो (असुरक्षित रूप से) विफल रहता है।

+0

स्पष्टीकरण के लिए धन्यवाद। हाँ, मैं समझता हूं कि एफएससी 2^20 शाखाएं बनाता है, अपवाद का कारण क्या है। लेकिन अगर मैं भेदभाव वाले यूनियनों में इंटरफेस डालता हूं (IChildClass1 के AllClasses = ChildClass1 | IChildClass2 के ChildClass2 | IChildClass3 के ChildClass3 ...) और भेदभाव वाले यूनियनों के साथ टुपल्स द्वारा समान * मैच * का उपयोग करें - कंपाइलर बिना किसी समस्या के प्रोजेक्ट को संकलित करता है - ऐसा लगता है जैसा संकलित कुछ कारणों से भिन्न होता है - अन्यथा तुलनात्मक रूप से तुलनाओं के लिए शाखाएं और भेदभाव वाले संघों के साथ तुलना – Vitaliy

+1

@ वितालिय जैसा मैंने कहा - मुझे बिल्कुल नहीं पता कि संकलक कैसे निर्णय लेता है। हालांकि, भेदभाव वाले संघों को संकलित करना इंटरफेस के खिलाफ परीक्षण करने के लिए काफी अलग है। डीयू के मामले में, संकलक जानता है कि केवल एक मामला होगा। इंटरफेस के मामले में, एक मान कई पैटर्न से मेल खाता है (यह एकाधिक इंटरफेस को कार्यान्वित कर सकता है)। –

+1

एलओएल। मेरे पास एचएलवीएम में एक ही बग था। http://flyingfrogblog.blogspot.co.uk/2010/04/variant-types-and-pattern-matching-in.html –

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