2009-07-02 12 views
7

निम्न कोड पूर्व शर्त पर विफल रहता है। क्या यह कोड अनुबंध में एक बग है?कोड अनुबंध के साथ iterators में बग?

static class Program 
{ 
    static void Main() 
    { 
     foreach (var s in Test(3)) 
     { 
      Console.WriteLine(s); 
     } 
    } 

    static IEnumerable<int>Test (int i) 
    { 
     Contract.Requires(i > 0); 
     for (int j = 0; j < i; j++) 
      yield return j; 
    } 
} 

उत्तर

2

मेरा अनुमान है कि इसे पुनरावर्तक की देरी प्रकृति के साथ करना है। याद रखें, अनुबंध उत्सर्जन अंतिम उत्सर्जित आईएल पर होगा, सी # कोड नहीं। इसका मतलब है कि आपको इटरेटर्स और लैम्ब्डा एक्सप्रेशन जैसे फीचर्स के लिए जेनरेट कोड पर विचार करना होगा।

यदि आप उस कोड को संकुचित करते हैं तो आप पाएंगे कि "i" वास्तव में एक पैरामीटर नहीं है। यह कक्षा में एक चर होगा जो इटरेटर को लागू करने के लिए प्रयोग किया जाता है। तो कोड वास्तव में अधिक की तरह निम्नलिखित

class IteratorImpl { 
    private int i; 
    public bool MoveNext() { 
    Contract.Require(i >0); 
    .. 
    } 
} 

लग रहा है मैं अनुबंध एपीआई के साथ बहुत परिचित नहीं हूँ, लेकिन मेरा अनुमान उत्पन्न कोड बहुत कठिन सत्यापित करने के लिए है।

+0

IteratorImpl के नियंत्रक के बजाय MoveNext पर आवश्यकता क्यों होनी चाहिए? –

+0

@pn, यह वही है जिसने सी # टीम ने इटरेटर्स को लागू करना चुना। किसी भी कोड जो इटरेटर के शरीर में दिखाई देता है, जेनरेट कोड के MoveNext विधि में समाप्त हो जाएगा। – JaredPar

+0

मेरा सवाल यह है कि क्या यह कोड अनुबंध में एक बग है या नहीं। ऐसा लगता है कि कोड अनुबंध फिर लेखक लेखक को समझ में नहीं आता है। –

0

याद रखें कि इटेटरेटर तब तक नहीं चलते हैं जब तक उनका गणना नहीं किया जाता है, और पीछे के अंत में कुछ विशेष सॉस में संकलित किए जाते हैं। जब यह है)

static IEnumerable<int> Test (int i) 
{ 
    Contract.Requires(i > 0); 
    return _Test(i); 
} 

private static IEnumerable<int> _Test (int i) 
{ 
    for (int j = 0; j < i; j++) 
     yield return j; 
} 

इस तरह टेस्ट (मानकों की जांच करेंगे: सामान्य पैटर्न आप का पालन करना चाहिए अगर आप, मानकों को मान्य करना चाहते हैं, और यह शायद अनुबंधों के लिए सच है एक आवरण समारोह है जिसे _Test() वापस लौटाया जाता है, जो वास्तव में केवल एक नई कक्षा देता है।

+0

यह कामकाज है। हालांकि, क्या मुझे अपना कोड बदलना चाहिए या यह एक बग है जिसे ठीक किया जाएगा? –

+0

यह तरीका है कि इटरेटर काम करते हैं - सी # इस व्यवहार को बदलने वाला नहीं है। यदि आपको विधि के पैरामीटर की जांच करने की आवश्यकता है, और इसे गणना पर नहीं करना चाहते हैं, तो आपको इसे दूसरी विधि में लपेटना होगा जो जांच करता है। मुझे अनुबंधों के बारे में पता नहीं है या फिर वे खुद को बेहतर करने वालों के साथ काम करने के लिए ठीक कर देंगे। – Talljoe

0

यहां इस विषय से संबंधित एक blog post है जो यूनिट परीक्षण, इटरेटर, देरी निष्पादन, और आप से संबंधित है।

विलंबित निष्पादन यहां मुद्दा है।

0

इस कोड .NET 4.0 (बस इसे करने की कोशिश) जहां interators में कोड संविदा का समर्थन कर रहे के अंतिम संस्करण के साथ काम करेंगे, लेकिन जैसा कि मुझे पता चला हाल ही में यह हमेशा ठीक से काम नहीं करता है (अधिक here पढ़ें)।

0

यह अतीत में CodeContract rewriter में एक समस्या हो सकती है। लेकिन वर्तमान संस्करण आपके उदाहरण पर ठीक लगता है। इटेटर/देरी मूल्यांकन आदि के साथ यहां कोई समस्या नहीं है। पैरामीटर को मैं मूल्य से पकड़ा गया है और पुनरावृत्ति के दौरान नहीं बदलेगा। अनुबंधों को केवल प्रत्येक पुनरावृत्ति के दौरान, परीक्षण के लिए कॉल की शुरुआत में ही जांचना चाहिए।

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