2012-05-16 38 views
12

Kullandığım proje, tek bir temel sınıftan miras alınan çok fazla sınıf içeriyor. Birim testlerinde alınan sonuçları türlere ve verilere göre karşılaştırmalıyım. koşulları liste hakkında yeterli içerdiğinde ben durumda türlerine göre maç karşılaştırma kullandığınızdaF # derleyici atıyor OutOfMemoryException

birçok farklı koşullar derleyici OutOfMemoryException atar. F # kodu aşağıdaki Örneğin

, derleme sırasında System.OutOfMemoryException (parametre hatası FS0193) yükseltir (ve derleme istisnası atılmadan önce yaklaşık 30 saniye sürdü) ben IEquatable arayüz ekleyebilir Emin

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 

benim IBaseClass böyle maç inşaat kullanımını önlemek veya IBaseClass arayüzüne int tür üyesi (veya enum) ekleyin ve türlerine göre değil maçı yapacak var sınıf, ancak bazıları tarafından int değeri.

Not MS VS 2010 ve MSVS 11 Beta aynı projeyi derlemek için çalıştı ve aynı derleyici hatası

Soru yaşadım: derleyici'nın OutOfMemoryException (benim durumumda olur Neden Bilindiği derleyici hata veya diğer sınırlamalar), bunu önlemek için benim eşleşmesi durumumu nasıl yeniden düzenlemeliyim? Ben ayrımcılık sendikaların içine sınıfları koymak ve maç benzeri kullanmak

Güncelleme karşılaştırma Fsc.exe Bu nasıl F # derleyicisi neden olur istisnasız

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 

Teşekkür

+0

"IChildClass1-20" yi yalnızca gösterim amacıyla mı kullandığınızı veya bu gerçek kodu mu kullandığınızı farz ediyorum. Derleyicinin kendisinin bir OutOfMemoryException (hiç bir cevabım yok) atması gerektiğini sanmıyorum (0) – Abel

+0

@Abel - evet, sınıf isimleri sadece gösterim amacıyla, sınıfların farklı isimlere sahip olması içindir. Eğer IChildClass1-18 içinde * AreEqual * kullanırsam makinemle ilgili not - proje derlenebilir, 19 ve daha fazlası - boom ...istisna – Vitaliy

cevap

9

projeyi derler Bu durumda tuplelarda desen eşleştirmeyi derler. Tam olarak bu özel sorunda çalıştığınız zaman tam olarak emin değilim ve derleyici başka bir yaklaşım kullandığında, ancak burada bu durumda neden başarısız olduğuna dair bir açıklama var ...

Eğer buradaki gibi bir eşleşme yazıyorsanız örneğiniz, derleyici esas olarak original (:? IChildClass1) için ilk kalıbı test eden bir karar ağacı oluşturur ve daha sonra iki dal oluşturur. İlk şube, compareWith'un da IChildClass1 olup olmadığını kontrol eder. Eğer evet ise, ilk davayı çalıştırır. desen eşleştirme kalan şube hem de çoğaltılamaz sonra, yani böyle bir şey (eğer ILSpy kullanarak vakaların az sayıda derlenmiş koduna bakılarak kontrol edebilirsiniz) olsun:

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) 
     (...) 

Bu Bu, oluşturulan kodun boyutunun, bu desen eşleştirmesindeki vakaların sayısı ile katlanarak orantılı olduğu anlamına gelir. 20 dava için derleyici, (şaşırtıcı derecede) başarısız olan 2^20 dal yaratmaya çalışır.

+0

açıklama için teşekkür ederiz. evet, Fsc'nin 2^20 dallar yarattığını anlıyorum, istisna ne sebep oluyor? Ama eğer ayrımcı sendikalar içine arayüzler koyarsam (tip AllClasses = IChildClass1 | ICCildClass2'nin ChildClass1 | ICCildClass3'ün ChildClass2'sini yazın ...) ve aynı * eşleştirmeyi ayrımcılık yapan sendikalarla eşleştirin - derleyici projeyi sorunsuz bir şekilde derler. derlenen bazı sebeplerden dolayı farklı - if - else şubeleri ile karşılaştırmalar yapar ve ayrımcılık yapan sendikalarla karşılaştırmalar – Vitaliy

+1

@Vitaliy Dediğim gibi derleyici tam olarak ne yapacağına karar vermez. Bununla birlikte, ayrımcı sendikaları derlemek, arayüzlere karşı test etmek için oldukça farklıdır. DU'ler söz konusu olduğunda, derleyici sadece bir vakanın ele alacağını bilir. Arabirimler söz konusu olduğunda, bir değer birden fazla modelle eşleşebilir (çoklu arayüzleri uygulayabilir). –

+1

LOL. HLVM'de de aynı hatayı vardı. http://flyingfrogblog.blogspot.co.uk/2010/04/variant-types-and-pattern-matching-in.html –