यदि कोई प्रकार एक उपप्रकार या वस्तु का प्रकार है, तो मैं कैसे जांच सकता हूं?


335

यह जाँचने के लिए कि क्या कोई प्रकार C # में दूसरे प्रकार का उपवर्ग है, यह आसान है:

typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true

हालांकि, यह विफल हो जाएगा:

typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false

क्या कोई तरीका है यह जांचने के लिए कि क्या कोई प्रकार एक उप-वर्ग या आधार वर्ग का स्वयं है, बिना किसी ORऑपरेटर का उपयोग किए या एक्सटेंशन विधि का उपयोग किए बिना ?

जवाबों:


499

जाहिर है, नहीं।

यहाँ विकल्प हैं:

Type.IsSubclassOf

जैसा कि आप पहले ही पता लगा चुके हैं, यह काम नहीं करेगा यदि दो प्रकार समान हैं, तो यहां एक नमूना LINQPad कार्यक्रम है जो प्रदर्शित करता है:

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

आउटपुट:

True
False

जो इंगित करता है कि Derivedएक उपवर्ग है Base, लेकिन Baseयह (जाहिर है) खुद का उपवर्ग नहीं है।

Type.IsAssignableFrom

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

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

यहां आपको निम्न आउटपुट मिलते हैं:

True
True
True

अंतिम Trueवहाँ इंगित करेगा, यदि विधि केवल पूछे गए प्रश्न का उत्तर देती है, जो uint[]विरासत में मिली है int[]या वे उसी प्रकार के हैं, जो स्पष्ट रूप से मामला नहीं है।

तो IsAssignableFromपूरी तरह से सही भी नहीं है।

is तथा as

साथ "समस्या" isऔर asअपने प्रश्न के संदर्भ में है कि वे आप वस्तुओं पर काम करते हैं और साथ कोड में सीधे प्रकारों में से एक है, और नहीं काम लिखने के लिए की आवश्यकता होगी Typeवस्तुओं।

दूसरे शब्दों में, यह संकलन नहीं करेगा:

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

और न ही यह होगा:

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

और न ही यह होगा:

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

निष्कर्ष

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

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

किस विधि से कौन सी विधि अधिक समझ में आती है:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

2
धन्यवाद! मैं इसे सही उत्तर के रूप में चिह्नित करूँगा (क्योंकि आपको 8 और मिनट इंतजार करना होगा) क्योंकि आपने उल्लेख किया है कि चेक को उलट देना है और MSDN प्रलेखन के लिए एक लिंक प्रदान किया है।
डेनियल टी।

71
ध्यान दें कि यह वास्तव में वह नहीं करता है जो प्रश्न के लिए पूछा गया था; यह निर्धारित नहीं करता है कि क्या एक प्रकार दूसरे का उपवर्ग है, बल्कि यह कि क्या एक प्रकार दूसरे के साथ संगत है। यूंट की एक सरणी इंट के सरणी का एक उपवर्ग नहीं है, लेकिन वे असाइनमेंट संगत हैं। IEnumerable <जिराफ> IEnumerable <पशु> का एक उपवर्ग नहीं है, लेकिन वे v4 में संगत काम कर रहे हैं।
एरिक लिपर्ट

जावा जैसे मेथड नेम में ऐसा करने का कोई तरीका नहीं है? `` `शून्य <? आधार का विस्तार> saveObject ((? ObjectToSave) `` `
ओलिवर डिक्सन

2
इसमें कैसे IsInstanceOfTypeफिट होगा ?
लेनार्ट

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



1

यदि आप इसे Xamarin Forms PCL प्रोजेक्ट में करने का प्रयास कर रहे हैं, तो उपरोक्त समाधान का उपयोग करने IsAssignableFromसे त्रुटि होती है:

त्रुटि: 'टाइप' में 'IsAssignableFrom' के लिए कोई परिभाषा नहीं है और कोई एक्सटेंशन विधि 'IsAssignableFrom' टाइप के पहले तर्क को स्वीकार करते हुए नहीं पाया जा सकता है (क्या आप एक निर्देश या विधानसभा संदर्भ का उपयोग कर याद कर रहे हैं?)

क्योंकि IsAssignableFromएक TypeInfoवस्तु के लिए पूछता है । आप इस GetTypeInfo()विधि का उपयोग कर सकते हैं System.Reflection:

typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())


0

मैं इस उत्तर को किसी के साथ साझा करने की आशा के साथ पोस्ट कर रहा हूं यदि यह एक बुरा विचार है और क्यों होगा। मेरे आवेदन में, मेरे पास टाइप की एक संपत्ति है जिसे मैं यह सुनिश्चित करने के लिए जांचना चाहता हूं कि यह टाइपोफ़ (ए) या टाइपोफ़ (बी) है, जहां बी ए किसी भी वर्ग से प्राप्त होता है, इसलिए मेरा कोड:

public class A
{
}

public class B : A
{
}

public class MyClass
{
    private Type _helperType;
    public Type HelperType
    {
        get { return _helperType; }
        set 
        {
            var testInstance = (A)Activator.CreateInstance(value);
            if (testInstance==null)
                throw new InvalidCastException("HelperType must be derived from A");
            _helperType = value;
        }
    }
}

मुझे लगता है कि मैं यहां थोड़ा सा अनुभव कर सकता हूं इसलिए किसी भी प्रतिक्रिया का स्वागत किया जाएगा।


2
उस विचार के साथ कुछ मुद्दे हैं: 1) प्रकार को एक पैरामीटर रहित निर्माता की जरूरत है या CreateInstance विफल हो जाएगा; 2) कास्टिंग करने के लिए (ए) शून्य वापस नहीं आता है यदि कलाकारों को नहीं बनाया जा सकता है, तो यह फेंकता है; 3) आपको वास्तव में नए उदाहरण की आवश्यकता नहीं है, इसलिए आपके पास एक बेकार आवंटन है। स्वीकृत उत्तर बेहतर है (हालांकि सही नहीं है)।
मार्सेल

प्रतिक्रिया के लिए धन्यवाद। बहुत मददगार।
बेसक्रेन

@baskren, शायद तब उनकी मददगार टिप्पणी को उभारते हैं। मैं # 1 उत्थान कर रहा था।
डेवलपर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.