वास्तव में "स्पेशल क्लास" क्या है?


114

संकलन करने के लिए निम्नलिखित की तरह कुछ प्राप्त करने में असफल होने के बाद:

public class Gen<T> where T : System.Array
{
}

त्रुटि के साथ

एक बाधा विशेष वर्ग `System.Array 'नहीं हो सकता

मैं सोचने लगा, क्या वास्तव में एक "विशेष वर्ग" है?

System.Enumजेनेरिक बाधा में निर्दिष्ट होने पर अक्सर लोगों को उसी तरह की त्रुटि मिलती है । मैं के साथ एक ही परिणाम मिला है System.Object, System.Delegate, System.MulticastDelegateऔर System.ValueTypeभी।

क्या उनमें से कुछ और हैं? मुझे C # में "विशेष वर्गों" पर कोई जानकारी नहीं मिल सकती है।

इसके अलावा, उन वर्गों के बारे में ऐसा क्या खास है कि हम उन्हें एक सामान्य प्रकार की बाधा के रूप में उपयोग नहीं कर सकते हैं?


14
मुझे नहीं लगता कि यह एक प्रत्यक्ष डुप्लिकेट है। सवाल यह नहीं है कि "मैं इसे एक बाधा के रूप में क्यों नहीं इस्तेमाल कर सकता", यह "ये विशेष वर्ग क्या हैं"। मैंने उन सवालों पर एक नज़र डाली है और वे सिर्फ यह बताते हैं कि एक बाधा के रूप में उपयोग करना क्यों बेकार होगा, यह बताते हुए कि वास्तव में "विशेष वर्ग" क्या है और इसे विशेष क्यों माना जाता है।
एडम हल्ड्सवर्थ

2
मेरे अनुभव में, जो कक्षाएं उपयोग की जाती हैं, लेकिन आप उन्हें सीधे उपयोग नहीं कर सकते हैं, केवल अन्य वाक्यविन्यास के माध्यम से, विशेष कक्षाएं हैं। Enum उसी श्रेणी में आता है। क्या वास्तव में उन्हें विशेष बनाता है, मुझे नहीं पता।
लास वी। कार्लसन

@AndyK वकील डे: यह सवाल अलग तरह का है। मैं "विशेष वर्ग" और / या इनमें से एक व्यापक सूची की परिभाषा के लिए पूछ रहा हूं। यह सवाल बस कारण पूछता है। System.Array एक सामान्य प्रकार की बाधा नहीं हो सकता है।
मिन्ट्स97

से प्रलेखन यह कहा गया "[...] केवल प्रणाली और compilers सरणी वर्ग से स्पष्ट रूप से निकाले जाते हैं कर सकते हैं।"। यह संभावना है कि यह वही है जो इसे एक विशेष वर्ग बनाता है - यह संकलक द्वारा विशेष रूप से व्यवहार किया जाता है।
आरबी।

1
@ आरबी .: गलत। इस तर्क का मतलब होगा System.Objectहै नहीं एक "विशेष क्लास", के रूप में यह मान्य है: public class X : System.Object { }, लेकिन System.Objectअभी भी एक "विशेष क्लास" है।
मंट्स97

जवाबों:


106

रोसलिन स्रोत कोड से, यह हार्डकोड प्रकार की सूची की तरह दिखता है:

switch (type.SpecialType)
{
    case SpecialType.System_Object:
    case SpecialType.System_ValueType:
    case SpecialType.System_Enum:
    case SpecialType.System_Delegate:
    case SpecialType.System_MulticastDelegate:
    case SpecialType.System_Array:
        // "Constraint cannot be special class '{0}'"
        Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type);
        return false;
}

स्रोत: Binder_Constraints.cs IsValidConstraintType
मैंने इसे GitHub खोज का उपयोग करके पाया है: "एक बाधा विशेष वर्ग नहीं हो सकती"


1
@kobi 702 संकलक त्रुटि CS0702 बन जाता है, जैसा कि संकलक आउटपुट में देखा गया है (जो इस प्रश्न को उद्धृत करने के लिए उपेक्षित है) और अन्य उत्तर।
आकाशवाणी

1
@ आकाश - धन्यवाद! मैंने संकलन करने का प्रयास किया और किसी कारण से त्रुटि संख्या नहीं मिली। इसके बाद मुझे यह पता लगाने में लगभग 5 मिनट लगे, और मेरी टिप्पणी को संपादित करने के लिए पर्याप्त समय नहीं था। दुखद कहानी।
कोबी

1
@ कोबी: आपको आउटपुट -विंडो को देखना होगा, वहां आपको सटीक कंपाइलर एरर कोड नंबर मिल जाएगा CS0702
टिम शाल्टर

9
तो अब असली सवाल यह है कि ये विशेष वर्ग क्यों हैं?
डेविड कहते हैं

@DavidGrinberg शायद इसका कारण यह है कि आप इन प्रकारों से सीधे विरासत में नहीं मिल सकते हैं (को छोड़कर object), या कम से कम इसके साथ कुछ करना है। इसके अलावा where T : Arrayपरख को टी के रूप में पारित करने की अनुमति होगी, जो कि शायद ज्यादातर लोग नहीं चाहते हैं।
IllidanS4 मोनिका को

42

मुझे एक ऐसे ही सवाल पर 2008 से एक जॉन स्कीट टिप्पणी मिली: क्यों System.Enumबाधा का समर्थन नहीं किया गया है।

मुझे पता है कि यह थोड़ा बंद विषय है , लेकिन उन्होंने एरिक लिपर्ट (सी # टीम) से इसके बारे में पूछा और उन्होंने इसका जवाब दिया:

सबसे पहले, आपका अनुमान सही है; अड़चनों पर प्रतिबंध भाषा के बड़े स्तर पर हैं और सीएलआर के लिए बहुत जरूरी नहीं है। (हम इन सुविधाओं को करने के लिए कुछ मामूली चीजें हैं जिन्हें हम सीएलआर में बदलना चाहते हैं कि कैसे असंख्य प्रकार निर्दिष्ट किए जाते हैं, लेकिन ज्यादातर यह भाषा का काम होगा।)

दूसरा, मैं व्यक्तिगत रूप से प्रतिनिधि बाधाओं, एनम बाधाओं और उन बाधाओं को निर्दिष्ट करने की क्षमता रखना पसंद करूंगा जो आज अवैध हैं क्योंकि कंपाइलर आपको खुद से बचाने की कोशिश कर रहा है। (यानी, सीलबंद प्रकारों को कानूनी रूप से अड़चन बना रहा है, इत्यादि।)

हालाँकि, शेड्यूलिंग प्रतिबंधों के कारण, हम संभवतः इन सुविधाओं को भाषा के अगले संस्करण में प्राप्त नहीं कर पाएंगे।


10
@YuvalItzchakov - Github \ MSDN को उद्धृत करना बेहतर है? C # टीम ने इस मुद्दे या इसी तरह के संबंध में एक ठोस जवाब दिया है। यह वास्तव में किसी को चोट नहीं पहुंचा सकता है। जॉन स्कीट ने सिर्फ उन्हें उद्धृत किया और सी # के लिए जाने पर यह बहुत विश्वसनीय है
अमीर पोपविच

5
परेशान होने की जरूरत नहीं है। मेरा मतलब यह नहीं था कि यह एक मान्य उत्तर नहीं है :) सिर्फ अपने विचारों को उस नींव पर साझा कर रहा था जो कि जोंसकेट है; पी
युवल इट्ज़चकोव

40
FYI करें BTW मुझे लगता है कि मैं तुम्हें वहाँ उद्धृत कर रहा हूँ। :-)
एरिक लिपर्ट

2
@ EricLippert - यह उद्धरण को और भी विश्वसनीय बनाता है।
अमीर पोपोविच

उत्तर में लिंक का डोमेन मर चुका है।
पैंग

25

MSDN के अनुसार यह कक्षाओं की एक स्थिर सूची है:

संकलक त्रुटि CS0702

बाधा विशेष वर्ग 'पहचानकर्ता' नहीं हो सकती है निम्नलिखित प्रकारों का उपयोग बाधाओं के रूप में नहीं किया जा सकता है:

  • System.Object
  • System.Array
  • System.Delegate
  • System.Enum
  • System.ValueType।

4
कूल, सही उत्तर की तरह लगता है, अच्छा लगता है! लेकिन System.MulticastDelegateसूची में कहां है?
मिन्ट्स97

8
@ Mints97: कोई विचार, प्रलेखन की कमी शायद?
टिम शिल्टर

लगता है जैसे आप भी इन वर्गों से विरासत में नहीं मिल सकते।
डेविड क्लेम्फनर

14

C # 4.0 भाषा विनिर्देश के अनुसार (कोडित: [10.1.5] टाइप पैरामीटर बाधाएं) दो बातें बताती हैं:

1] टाइप ऑब्जेक्ट नहीं होना चाहिए। क्योंकि सभी प्रकार की वस्तुएं प्राप्त होती हैं, इस तरह की बाधा का कोई प्रभाव नहीं पड़ता अगर इसे अनुमति दी जाती।

2] यदि T की कोई प्राथमिक बाधा नहीं है या पैरामीटर की कमी नहीं है, तो इसका प्रभावी आधार वर्ग वस्तु है।

जब आप एक सामान्य वर्ग को परिभाषित करते हैं, तो आप उस प्रकार के प्रकारों के लिए प्रतिबंध लागू कर सकते हैं जो क्लाइंट कोड प्रकार का उपयोग तब कर सकता है जब वह अपनी कक्षा को त्वरित करता है। यदि क्लाइंट कोड किसी प्रकार की बाधा का उपयोग करके आपकी कक्षा को तुरंत रोकने की कोशिश करता है, तो परिणाम एक संकलन-समय त्रुटि है। इन प्रतिबंधों को अड़चन कहा जाता है। प्रासंगिक कीवर्ड का उपयोग करके बाधाओं को निर्दिष्ट किया जाता है। यदि आप एक संदर्भ प्रकार होने के लिए एक सामान्य प्रकार को बाध्य करना चाहते हैं, तो उपयोग करें: वर्ग।

public class Gen<T> where T : class
{
}

यह जेनेरिक प्रकार को मूल्य प्रकार, जैसे कि इंट या एक संरचना आदि से प्रतिबंधित करेगा।

इसके अलावा, बाधा विशेष वर्ग 'पहचानकर्ता' नहीं हो सकती है, निम्नलिखित प्रकारों का उपयोग बाधाओं के रूप में नहीं किया जा सकता है:

  • System.Object
  • System.Array
  • System.Delegate
  • System.Enum
  • System.ValueType।

12

फ्रेमवर्क में कुछ निश्चित वर्ग होते हैं जो प्रभावी रूप से उनसे प्राप्त सभी प्रकार की विशेष विशेषताओं से गुजरते हैं, लेकिन उन विशेषताओं के अधिकारी नहीं होते हैं । सीएलआर स्वयं उन वर्गों के लिए बाधाओं के रूप में उपयोग करने के खिलाफ कोई प्रतिबंध नहीं लगाता है, लेकिन उनके लिए बाध्य सामान्य प्रकार गैर-विरासत वाले विशेषताओं को प्राप्त नहीं करेगा जिस तरह से ठोस प्रकार होंगे। C # के रचनाकारों ने फैसला किया कि क्योंकि ऐसा व्यवहार कुछ लोगों को भ्रमित कर सकता है, और वे इसके लिए कोई उपयोगिता देखने में विफल रहे, उन्हें इस तरह की बाधाओं को रोकने के बजाय उन्हें व्यवहार करने की अनुमति देना चाहिए जैसा कि वे CLR में करते हैं।

यदि, उदाहरण के लिए, किसी को लिखने की अनुमति थी void CopyArray<T>(T dest, T source, int start, int count):; एक पास करने के लिए destऔर sourceतरीकों के लिए जो प्रकार के एक तर्क की उम्मीद कर सकता है System.Array; आगे, एक संकलन समय मान्यता है कि मिलेगा destऔर sourceसंगत सरणी प्रकार थे, लेकिन एक सरणी का उपयोग करने का उपयोग कर सकते तत्वों के लिए सक्षम नहीं होगा []ऑपरेटर।

Arrayएक बाधा के रूप में उपयोग करने की अक्षमता ज्यादातर काम करने के लिए बहुत आसान है, चूंकि void CopyArray<T>(T[] dest, T[] source, int start, int count)लगभग सभी स्थिति में काम करेगी जहां पूर्व विधि काम करेगी। हालांकि, यह एक कमजोरी है: पूर्व विधि इस परिदृश्य में काम करेगी कि एक या दोनों तर्क उन System.Arrayमामलों को खारिज करते समय प्रकार के थे जहां तर्क असंगत सरणी प्रकार हैं; एक अधिभार जोड़ने जहां दोनों प्रकार के तर्क थे System.Arrayकोड को स्वीकार किए जाने वाले अतिरिक्त मामलों को स्वीकार करना होगा, लेकिन इसे गलत तरीके से स्वीकार किए जाने वाले मामलों को भी बनाना चाहिए।

मुझे लगता है कि ज्यादातर विशेष बाधाओं को गैरकानूनी घोषित करने का निर्णय है। केवल वही जिसका शून्य अर्थ होगा System.Object[चूंकि अगर वह एक बाधा के रूप में कानूनी था, तो कुछ भी उसे संतुष्ट करेगा]। System.ValueTypeशायद बहुत उपयोगी नहीं होगा, क्योंकि प्रकार के संदर्भ ValueTypeवास्तव में मूल्य प्रकारों के साथ बहुत अधिक नहीं होते हैं, लेकिन यह प्रतिबिंबित करने वाले मामलों में कुछ मानों को बहुत कम कर सकता है। दोनों System.Enumऔर System.Delegateकुछ असली उपयोग करता है, लेकिन जब से सी # के रचनाकारों उनमें से नहीं सोचा था कि वे कोई अच्छे कारण के लिए गैरकानूनी घोषित कर रहे हैं।


10

निम्नलिखित सीएलआर में C # 4th संस्करण के माध्यम से पाया जा सकता है:

प्राथमिक बाधाएँ

एक प्रकार का पैरामीटर शून्य प्राथमिक बाधाओं या एक प्राथमिक बाधा को निर्दिष्ट कर सकता है। एक प्राथमिक बाधा एक संदर्भ प्रकार हो सकता है जो एक वर्ग की पहचान करता है जिसे सील नहीं किया जाता है। आप निम्न विशेष संदर्भ प्रकारों में से एक को निर्दिष्ट नहीं कर सकते हैं: System.Object , System.Array , System.Delegate , System.MulticastDelegate , System.ValueType , System.Enum , या System.Void । एक संदर्भ प्रकार की बाधा को निर्दिष्ट करते समय, आप संकलक का वादा कर रहे हैं कि एक निर्दिष्ट प्रकार का तर्क या तो उसी प्रकार का होगा या बाधा प्रकार से व्युत्पन्न प्रकार का होगा।


यह भी देखें: सी # लोकसभा खंड 10.1.4.1: एक वर्ग के प्रकार के प्रत्यक्ष आधार वर्ग निम्नलिखित प्रकार के किसी भी नहीं होना चाहिए: System.Array, System.Delegate, System.MulticastDelegate, System.Enum, या System.ValueType। इसके अलावा, एक सामान्य वर्ग की घोषणा System.Attributeएक प्रत्यक्ष या अप्रत्यक्ष आधार वर्ग के रूप में उपयोग नहीं कर सकती है ।
जीरो वेनवेल

5

मुझे नहीं लगता, कि "विशेष वर्ग" / "विशेष प्रकार" की कोई आधिकारिक परिभाषा मौजूद है।

आप उनके बारे में सोच सकते हैं कि ए प्रकार, जिन्हें "नियमित" प्रकार के शब्दार्थ के साथ इस्तेमाल नहीं किया जा सकता है:

  • आप उन्हें सीधे नहीं कर सकते हैं;
  • आप सीधे उनसे कस्टम प्रकार वारिस नहीं कर सकते;
  • उनके साथ काम करने के लिए कुछ संकलक जादू है (वैकल्पिक रूप से);
  • उनके उदाहरणों का प्रत्यक्ष उपयोग कम से कम बेकार (वैकल्पिक रूप से; कल्पना करें, कि आपने ऊपर जेनेरिक बनाया है, आप कौन सा सामान्य कोड लिखने जा रहे हैं?)

पुनश्च मैं System.Voidसूची में जोड़ना चाहते हैं ।


2
System.Voidएक सामान्य बाधा के रूप में उपयोग किए जाने पर एक पूरी तरह से अलग त्रुटि देता है =)
मिन्ट्स97

@ Mints97: सच है। लेकिन अगर सवाल "विशेष" के बारे में है, तो हाँ, voidबहुत विशेष है। :)
डेनिस

@ डेनिस: कोड जिसमें एक प्रकार के दो पैरामीटर होते हैं जो एक से दूसरे में डेटा स्थानांतरित करने के System.Arrayलिए तरीकों का उपयोग करने के लिए विवश हो सकते हैं Array.Copy; एक प्रकार के मापदंडों के साथ कोड, System.Delegateउन Delegate.Combineपर उपयोग करने में सक्षम होगा और परिणाम को उचित प्रकार में डाल देगा । एक सामान्य ज्ञात प्रकार का प्रभावी उपयोग करना Enumप्रत्येक प्रकार के लिए एक बार परावर्तन का उपयोग करना होगा, लेकिन एक सामान्य HasAnyFlagविधि गैर-सामान्य विधि की तुलना में 10x तेज हो सकती है।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.