2012-01-07 7 views
17

सी # कोड का निम्न भाग संकलन नहीं करता है:बेस क्लास विनिर्देश का अर्थ फिर से सी # में क्यों निर्भर नहीं हो सकता है?

public class A 
{ 
    public interface B { } 
}    
public class C 
    : A, 
     C.B // Error given here: The type name 'B' does not exist in the type 'C'. 
{ } 

public class D : C.B // Compiles without problems if we comment out 'C.B' above. 
{ } 

यह व्यवहार सही सी # 4.0 विनिर्देश के अनुसार (पैरा 10.1.4.1) है: प्रत्यक्ष आधार का अर्थ निर्धारित करते समय

कक्षा विनिर्देश ए कक्षा बी का ए, बी का प्रत्यक्ष आधार वर्ग अस्थायी रूप से ऑब्जेक्ट माना जाता है। सहजता से यह सुनिश्चित करता है कि बेस क्लास विनिर्देश का अर्थ पुन: प्रयास नहीं कर सकता है।

मेरा प्रश्न है: इस व्यवहार की अनुमति क्यों नहीं है?

इंटेलिसेंस में इसके साथ कोई समस्या नहीं है - हालांकि मुझे पता है कि विजुअल स्टूडियो क्रैश को देखने के बाद इंटेलिजेंस कुछ बुरा वर्ग संयोजन को समझने की कोशिश करता है जब वेरिएंट जेनरिक के साथ कुछ बुरा वर्ग संयोजन को समझने की कोशिश करता है।

विनिर्देश से उपरोक्त उद्धरण के लिए इंटरनेट खोजना कुछ भी नहीं पैदा करता है, इसलिए मुझे लगता है कि यह अभी तक कहीं भी नहीं लाया गया है।

मुझे परवाह क्यों है? मैंने कोड के निम्नलिखित भाग को डिज़ाइन किया:

// The next three classes should really be interfaces, 
// but I'm going to override a method later on to prove my point. 
// This is a container class, that does nothing except contain two classes. 
public class IBagContainer<Bag, Pointer> 
    where Bag : IBagContainer<Bag, Pointer>.IBag 
    where Pointer : IBagContainer<Bag, Pointer>.IPointer 
{ 
    // This could be an interface for any type of collection. 
    public class IBag 
    { 
     // Insert some object, and return a pointer object to it. 
     // The pointer object could be used to speed up certain operations, 
     // so you don't have to search for the object again. 
     public virtual Pointer Insert(object o) { return null; } 
    } 
    // This is a pointer type that points somewhere insice an IBag. 
    public class IPointer 
    { 
     // Returns the Bag it belongs to. 
     public Bag GetSet() { return null; } 
    } 
} 
// This is another container class, that implements a specific type of IBag. 
public class BinarySearchTreeContainer<Tree, Node> : IBagContainer<Tree, Node> 
    where Tree : BinarySearchTreeContainer<Tree, Node>.BinarySearchTree 
    where Node : BinarySearchTreeContainer<Tree, Node>.BinarySearchTreeNode 
{ 
    // This is your basic binary search tree. 
    public class BinarySearchTree : IBagContainer<Tree, Node>.IBag 
    { 
     // We can search for objects we've put in the tree. 
     public Node Search(object o) { return null; } 

     // See what I did here? Insert doesn't return a Pointer or IPointer, 
     // it returns a Node! Covariant return types! 
     public override Node Insert(object o) { return null; } 
    } 
    // A node in the binary tree. This is a basic example of an IPointer. 
    public class BinarySearchTreeNode : IBagContainer<Tree, Node>.IPointer 
    { 
     // Moar covariant return types! 
     public override Tree GetSet() { return null; } 
     // If we maintain next and prev pointers in every node, 
     // these operations are O(1). You can't expect every IBag 
     // to support these operations. 
     public Node GetNext() { return null; } 
     public Node GetPrev() { return null; } 
    } 
} 

देखो, हमने कॉन्वेंट रिटर्न प्रकार प्राप्त किए हैं! हालांकि एक छोटी सी जानकारी है।

बाइनरीशर्च ट्री को तुरंत चालू करने का प्रयास करें। ऐसा करने के लिए, हमें कुछ उपयुक्त वृक्ष और नोड कक्षाओं के लिए BinarySearchTreeContainer.BinarySearchTree निर्दिष्ट करने की आवश्यकता है। वृक्ष के लिए, हम बाइनरीशर्च ट्री का उपयोग करना चाहते हैं, जिसके लिए हमें बाइनरीशर्च ट्रीकंटनर निर्दिष्ट करना होगा। बाइनरीशर्च ट्री ... और हम अटक गए हैं।

यह अनिवार्य रूप से curiously recurring template pattern (सीआरटीपी) है। दुर्भाग्य से, हम यह CRTP में के रूप में ठीक नहीं कर सकते:

public class BinarySearchTreeContainer 
    : BinarySearchTreeContainer 
     <BinarySearchTreeContainer.BinarySearchTree, 
     BinarySearchTreeContainer.BinarySearchTreeNode> { } 
public class IBagContainer 
    : IBagContainer 
     <IBagContainer.IBag, 
     IBagContainer.IPointer> { } 

(...) 
BinarySearchTreeContainer.BinarySearchTree tree 
    = new BinarySearchTreeContainer.BinarySearchTree(); 
tree.Search(null); 
IBagContainer.IBag bag = tree; // No cast! 
//bag.Search(null); // Invalid! 
//BinarySearchTreeContainer.BinarySearchTreeNode node 
// = bag.Insert(null); // Invalid! 

और हम वापस अपने मूल प्रश्न के कर रहे हैं: शीर्ष दो वर्ग परिभाषाओं सी # विनिर्देश द्वारा अनुमति नहीं है। यदि इस वर्ग की परिभाषा की अनुमति थी, तो मेरे बाइनरी खोज पेड़ उपयोग योग्य होंगे। अभी, वे केवल संकलित करते हैं: उनका उपयोग नहीं किया जा सकता है।

+1

+1 सीआरटीपी के रूप में दिलचस्प है ... मूर्ख प्रकार के सिस्टम :) दिलचस्प सवाल, हालांकि। यह सुनिश्चित नहीं है कि पोस्ट में एम्बेड किए गए व्यक्तिपरक ध्वनि वाले प्रश्न के साथ यह कैसे उचित होगा, हालांकि ऐसा लगता है कि बहुत सारे उद्देश्य उत्तर हैं। –

+0

यह वास्तव में उपयोगी होगा यदि नेस्टेड कक्षाओं को अपने बाहरी वर्गों के आंतरिक लोगों तक पहुंच की आवश्यकता हो ... जब तक ऐसा नहीं होता है, तब तक आप अपने युक्त कक्षाओं के बाहर नेस्टेड कक्षाएं घोषित कर सकते हैं और आप कर चुके हैं। – Nuffin

उत्तर

21

मैंने पिछले कुछ वर्षों में अनगिनत घंटों तक आपके द्वारा उठाए गए मुद्दों से संघर्ष किया है। आपके द्वारा उठाए गए सभी मुद्दों की एक विस्तृत चर्चा में मुझे टाइप करने में कई घंटे लगेंगे, इसलिए मैं संक्षेप में सारांश दूंगा:

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

जाहिर है कि यह एक अच्छी जगह नहीं है। जब आप किसी फ़ाइल में कक्षाओं को फिर से ऑर्डर करते हैं तो हम नहीं चाहते हैं कि सी # प्रोग्राम का अर्थ भिन्न हो!

दूसरा, हम मेटाडेटा में क्या प्रदर्शित किया जा सकता है इसके बावजूद हम बाध्य हैं।

तीसरा, ऐतिहासिक रूप से हम द्वारा मेटाडेटा में कुशलतापूर्वक उत्सर्जित किया जा सकता है। मेटाडेटा उत्सर्जकों के पिछले संस्करणों में प्रदर्शन या शुद्धता के मुद्दे थे यदि आपने बाहरी प्रकारों से पहले आधार प्रकारों या आंतरिक प्रकारों से पहले व्युत्पन्न प्रकारों को उत्सर्जित करने का प्रयास किया था। (मैंने एक टोपोलॉजिकल सॉर्टर लिखकर इसे संबोधित करने के लिए सी # 4 में प्रयास किया था, जो किसी भी अस्तित्व में एक कुशल आदेश मिलेगा, लेकिन परिवर्तन पर्याप्त जटिल और खतरनाक साबित हुआ कि हमने रोज़लिन तक परिवर्तन नहीं करने का फैसला किया। रोज़लिन में हम इसका उपयोग कर रहे हैं एक पूरी तरह से अलग emitter।)

चौथा, यह दुर्लभ है कि इस प्रकार के टोपोलॉजी वास्तविक उत्पादन कोड में बदल जाते हैं; आप स्पष्ट रूप से उस नियम के लिए अपवाद हैं।

पांचवें, भाषा के लिए हमारे प्रमुख लक्ष्यों में से एक यह है कि इसे "गुणवत्ता का गड्ढा" भाषा बनाना है, जहां भाषा की विशेषताएं एक ऐसे प्रोग्राम लिखने के लिए प्रेरित करती हैं जो सही और समझदार दोनों हो। सी ++ टेम्पलेट्स में दिखाई देने वाले पागल "उत्सुकता से आवर्ती" पैटर्न के प्रकार की अनुमति देना स्पष्ट रूप से सी # भाषा टीम का लक्ष्य नहीं है। हम सैद्धांतिक रूप से पूर्ण प्रकार की प्रणाली प्रदान करने में रुचि नहीं रखते हैं; हम यह प्रतिनिधित्व करना आसान बनाने में रुचि रखते हैं कि एक कर्मचारी एक प्रकार का व्यक्ति है।

ये सभी कारक बेस क्लास और नेस्टेड क्लास रिश्तों में परिपत्र बनाने के खिलाफ काम कर रहे हैं और अधिक कानूनी हैं। जितना अधिक मैं व्यक्तिगत रूप से बेस प्रकारों में परिपत्रों को हल करने के लिए एक अच्छी तरह से स्थापित प्रणाली के साथ आने की चुनौती का आनंद लेता हूं, जो मौजूदा कोड को तोड़ता नहीं है, यह पर्याप्त प्राथमिकता नहीं है; हमारे पास Roslyn के लिए उन चीजों की एक लंबी सूची है जो हम सुधारना चाहते हैं, और बेस क्लास रिज़ॉल्यूशन एल्गोरिदम उस सूची के शीर्ष से बहुत दूर है।

+3

पर्याप्त मेला। मुझे डर था कि यह 'कीड़े का प्रकार' मुद्दा था - मुझे लगता है मुझे कुछ और सोचना होगा। यदि आपके पास उन्हें जोड़ने का समय होगा तो मुझे आपके कुछ उदाहरणों का उल्लेख करना अच्छा लगेगा! –

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