2012-01-12 13 views
8

मैं कोड अनुबंधों को गलत समझ सकता हूं, लेकिन यहां मेरी स्थिति है। मैं एक अपेक्षाकृत सरल अनुबंध को जोड़ने के लिए कोशिश कर रहा हूँकोड अनुबंध और विरासत की समस्याएं, क्या चलती है?

interface IFetch<T> // defined in another DLL 
{ 
    T Fetch(int id); 
} 

interface IUserFetch : IFetch<User> 
{ 
    IEnumerable<User> GetUsersLoggedIn(); 
} 

class UserFetch : IUserFetch 
{ 
    public User Fetch(int id) 
    { 
     return (User) Database.DoStuff (id); 
    } 

    public IEnumerable<User> GetUsersLoggedIn() 
    { 
     return (IEnumerable<User>) Database.DoMoreStuff(); 
    } 
} 

:

मैं निम्नलिखित कोड है Contract.Requires (id != 0);, और मैं इसे Fetch पर मान्य चाहते हैं। जब मैं इसे सीधे प्राप्त करने के लिए जोड़ता हूं, तो मुझे चेतावनी मिलती है कि Method Fetch(int id) implements interface 3rdParty.IFetch<User> and thus cannot add Requires

मैंने एक अमूर्त कोड अनुबंध क्लास को IFetch लागू करने के लिए बनाया है और इसे ContractClass और ContractClassFor विशेषताओं का उपयोग करके उपयोगकर्ताफ़ेच से/पर इंगित किया है। मुझे अभी भी CodeContracts: The class 'FetchUserContracts' is supposed to be a contract class for '3rdParty.IFetch<User>', but that type does not point back to this class. जैसी त्रुटि मिलती है, हालांकि, तृतीयParty.IFetch एक सामान्य प्रकार है, मुझे नहीं लगता कि मैं इसे विशेष रूप से कोड अनुबंध भी डाल सकता हूं।

क्या समस्या स्पष्ट हो गई है, और यदि हां, तो मैं इसे कैसे हल करूं?

+0

संभावित डुप्लिकेट: http://stackoverflow.com/questions/3414586 –

+0

@RobertHarvey: मैं ज्यादातर कि ले लेंगे, सिवाय मेरी समस्या जेनरिक से अधिक स्टेम करने लगता है –

उत्तर

5

मेरा मानना ​​है कि Ɖiamond ǤeezeƦ के जवाब सही है। मैं बस थोड़ा सा व्याख्या जोड़ूंगा।

आप एक बंद निर्मित प्रकार (जैसे IFetch<User>) में एक विधि में Contract.Requires सजावट नहीं जोड़ सकते हैं। आपको इसे खुले निर्मित प्रकार (IFetch<>) में जोड़ना होगा। इसका कारण यही कारण है कि आप Contract.Requires सजावट को एक ठोस विधि में सजा नहीं सकते हैं जिसका उपयोग इंटरफ़ेस को लागू करने के लिए किया जाता है: कोड अनुबंध को संकलित समय पर सत्यापित करने के लिए डिज़ाइन किया गया है जब ऑब्जेक्ट इंस्टेंस का पूर्ण प्रकार अज्ञात हो सकता है।

मान लीजिए कि आपने कंक्रीट विधि कार्यान्वयन पर अनुबंध डालने की अनुमति दी है।

public User Fetch(int id) 
{ 
    Contract.Requires (id != 0);, 
    return (User) Database.DoStuff (id); 
} 

अब कोई इंटरफ़ेस प्रकार की एक चर का उपयोग करने की कोशिश की लगता है।

class DataDisplayer<T> 
{ 
    Label myLabel = new Label(); 
    public void Display(IFetch<T> fetch, int id) 
    { 
     myLabel.Text = fetch.Fetch(id).ToString(); 
    } 
} 

क्या यह अनुबंध उल्लंघन की अनुमति देता है या नहीं? यह कहना असंभव है, क्योंकि हम नहीं जानते कि fetch का ठोस प्रकार रनटाइम पर होगा।

IFetch<User> जैसे किसी विशेष बंद प्रकार के प्रकार पर अनुबंध डालने से इस समस्या का समाधान नहीं होता है। हम अभी भी नहीं जानते कि कॉलिंग कोड में टी किस प्रकार का है।

लिस्कोव प्रतिस्थापन सिद्धांत, जो सभी ऑब्जेक्ट ओरिएंट प्रोग्रामिंग का आधारशिला है, का अर्थ है कि हम कभी भी किसी ऑब्जेक्ट के रनटाइम प्रकार के बारे में कुछ भी नहीं मान सकते हैं जो चर के प्रकार इंगित करता है। और चूंकि वेरिएबल का प्रकार एक सामान्य इंटरफ़ेस हो सकता है, इसलिए कोड अनुबंध सामान्य इंटरफ़ेस परिभाषा में क्या है, कॉलर पर कोई अतिरिक्त बोझ नहीं डाल सकता है।

इसलिए, Contract.Requires, खुले निर्माण प्रकार पर डाल दिया जाना चाहिए ताकि किसी भी वस्तु है कि इंटरफ़ेस को लागू करता है आवश्यकता है, और इंटरफ़ेस प्रकार की एक चर के माध्यम से विधि के लिए किसी भी संभावित कॉल करना होगा सम्मान के साथ शुद्धता के लिए सत्यापित किया जा सकता उस आवश्यकता के लिए।

10

आप उदाहरण के लिए, अनुबंध लागू करने के लिए एक अमूर्त वर्ग बनाने की जरूरत:

[ContractClassFor(typeof(IFetch<>))] 
public abstract class ContractClassForIFetch<T> : IFetch<T> 
{ 
    public T Fetch(int id) 
    { 
     Contract.Requires(id != 0); 
     return default(T); 
    } 
} 

और IFetch के लिए निम्न ContractClass विशेषता जोड़ें:

[ContractClass(typeof(ContractClassForIFetch<>))] 
public interface IFetch 
{ 
    T Fetch(int id); 
} 
+0

भी देखें इस [संबंधित क्यू/A] (https: //stackoverflow.com/questions/3414586/) – orad

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