जांचें कि क्या 'T' एक वर्ग / इंटरफ़ेस को विरासत या लागू करता है


92

क्या परीक्षण करने का कोई तरीका है यदि T विरासत में मिला / क्लास / इंटरफ़ेस लागू करता है?

private void MyGenericClass<T> ()
{
    if(T ... inherits or implements some class/interface
}

4
यह काम करने के लिए प्रकट होता है ... यदि (टाइपोफ़ (टेस्टक्लास) .IsAssignableFrom (टाइपोफ़ (टी))), क्या कोई मेरे संदेह की पुष्टि कर सकता है? धन्यवाद!
user1229895

मुझे पूरा यकीन है कि यह उत्तर कई बार दोहराया जाता है!
फेलिक्स के।

3
फेलिक्स के भले ही इस उत्तर को कई बार दोहराया गया हो, यह बहुत से लोगों को कई बार मदद भी करता है;) ... मेरे जैसे पांच मिनट पहले :)
शमूएल

जवाबों:


136

Type.sAssignableFrom () नामक एक विधि है ।

यह जाँचने के लिए कि क्या Tविरासत / उपकरण हैं Employee:

typeof(Employee).IsAssignableFrom(typeof(T));

यदि आप .NET कोर को लक्षित कर रहे हैं, तो विधि TypeInfo में चली गई है:

typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())

आपको एक उदाहरण के साथ अपना जवाब अपडेट करना चाहिए, जैसे टाइपोफ़ (टी) .IAAignignableFrom (टाइपोफ़ (IMyInterface))
डॉ। एंड्रयू बर्नेट-थॉम्पसन

नहीं किया गया नाइकी; पुराना उत्तर अभी भी है। :) मैंने दूसरी जोड़ी ली, यह पता लगाने के लिए कि क्या गलत है। वैसे भी, .net फ्रेमवर्क के फिर से, अच्छी सुविधा।
शमूएल

वास्तव में, जिस तरह से आपने उल्लेख किया है वह वह तरीका है जैसा मैंने कुछ समय पहले किया था। मैंने इसे ठीक किया। पिछली टिप्पणियाँ देखें। T inherits Uवास्तव में अनुवाद करता है typeof(T).IsAssignableFrom(typeof(U))
निकेई

3
जबकि यह लगभग काम करता है, एक ऐसा मुद्दा है जहां अगर Tकिसी अन्य प्रकार के लिए विवश किया जाता है TOther, तो जब निष्पादित किया जाता है, typeof(T)तो वास्तव में मूल्यांकन करेंगे typeof(TOther)और न कि Tआप जिस प्रकार से वास्तव में उत्तीर्ण हुए थे, और उस मामले में, typeof(SomeInterface).IsAssignableFrom(typeof(T))विफल हो जाएगा (यह मानते हुए TOtherभी लागू नहीं होता है SomeInterface), भले ही आपके ठोस प्रकार ने कार्यान्वित किया हो SomeInterface
डेव कजिनो

1
.Net कोर में IsAssignableFromकी TypeInfoकक्षा केवल, यह केवल तर्क के रूप में स्वीकार करता है TypeInfo तो नमूना निम्न होना चाहिए:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
करने के लिए Ka


16

यदि आप संकलन के दौरान जांच करना चाहते हैं: यदि वांछित इंटरफ़ेस / वर्ग को लागू T नहीं करता है तो त्रुटि , आप निम्नलिखित बाधा का उपयोग कर सकते हैं

public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
    //Code of my method here, clean without any check for type constraints.
}

मुझे आशा है कि वह मदद करेंगे।


12

सही सिंटैक्स है

typeof(Employee).IsAssignableFrom(typeof(T))

प्रलेखन

वापसी मान: true यदि cऔर वर्तमान Typeएक ही प्रकार का प्रतिनिधित्व करते हैं, या यदि वर्तमान Typeविरासत की पदानुक्रम में है c, या यदि वर्तमान Typeएक है interfaceकि cलागू होता है, या यदि cएक सामान्य प्रकार का पैरामीटर है और वर्तमान Typeएक बाधा का प्रतिनिधित्व करता है c, या यदि cएक मान प्रकार का प्रतिनिधित्व करता है और वर्तमान ( विजुअल बेसिक में) का Typeप्रतिनिधित्व करता है । यदि इनमें से कोई भी स्थिति नहीं है , या यदि है ।Nullable<c>Nullable(Of c)falsetruecnull

स्रोत

व्याख्या

यदि Employee IsAssignableFrom Tफिर से Tविरासत में मिला है Employee

उपयोगितायें

typeof(T).IsAssignableFrom(typeof(Employee)) 

true तभी लौटता है जब या तो

  1. Tऔर Employeeउसी प्रकार का प्रतिनिधित्व करते हैं; या,
  2. Employeeसे विरासत में मिला है T

यह कुछ मामलों में उपयोग करने का इरादा हो सकता है , लेकिन मूल प्रश्न (और अधिक सामान्य उपयोग) के लिए, यह निर्धारित करने के लिए कि Tविरासत class/ कुछ का interfaceउपयोग कब लागू होता है :

typeof(Employee).IsAssignableFrom(typeof(T))

9

वास्तव में सभी का मतलब क्या है:

typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true

आप सचमुच सकता है, क्योंकि से आवंटित एक का एक उदाहरण DerivedTypeएक का एक उदाहरण के लिए BaseType:

DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base

कब

public class BaseType {}
public class DerivedType : BaseType {}

और कुछ ठोस उदाहरण यदि आपको अपने सिर को उसके चारों ओर लपेटने में परेशानी हो रही है:

(LinqPad के माध्यम से, इसलिए HorizontalRunऔर Dump)

void Main()
{
    // http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface

    var b1 = new BaseClass1();

    var c1 = new ChildClass1();
    var c2 = new ChildClass2();
    var nb = new nobase();

    Util.HorizontalRun(
        "baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
        b1.IsAssignableFrom(typeof(BaseClass1)),
        c1.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(ChildClass1)),
        c2.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(ChildClass2)),
        nb.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(nobase))
        ).Dump("Results");

    var results = new List<string>();
    string test;

    test = "c1 = b1";
    try {
        c1 = (ChildClass1) b1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "b1 = c1";
    try {
        b1 = c1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "c2 = b1";
    try {
        c2 = (ChildClass2) b1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "b1 = c2";
    try {
        b1 = c2;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    results.Dump();
}

// Define other methods and classes here
public static class exts {
    public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
        return typeof(T).IsAssignableFrom(baseType);
    }
}


class BaseClass1 {
    public int id;
}

class ChildClass1 : BaseClass1 {
    public string name;
}

class ChildClass2 : ChildClass1 {
    public string descr;
}

class nobase {
    public int id;
    public string name;
    public string descr;
}

परिणाम

baseclass-> baseclass

सच

child1-> baseclass

असत्य

baseclass-> child1

सच

child2-> baseclass

असत्य

baseclass-> child2

सच

nobase-> baseclass

असत्य

baseclass-> nobase

असत्य

तथा

  • विफल: c1 = b1
  • बी 1 = सी 1
  • विफल: c2 = b1
  • बी 1 = सी 2

2

मेरा मानना ​​है कि वाक्य रचना है: typeof(Employee).IsAssignableFrom(typeof(T));


यह अभीष्ट वाक्य-विन्यास है। +1
ल्यूक

0

हालांकि IsAssignableFrom अन्य लोगों द्वारा बताए गए तरीके से सबसे अच्छा तरीका है, अगर आपको केवल यह जांचने की आवश्यकता है कि क्या एक वर्ग दूसरे से विरासत में मिला typeof(T).BaseType == typeof(SomeClass)है, काम भी करता है।


वह तब तक काम करता है जब तक कि SomeClassसीधे से प्राप्त नहीं किया जाता है BaseClass
सनकैट

0

वैकल्पिक तरीके यह बताने के लिए कि क्या कोई ऑब्जेक्ट oएक वर्ग को विरासत में मिला है या एक इंटरफ़ेस लागू करना है isऔर asऑपरेटरों का उपयोग करना है ।

यदि आप केवल यह जानना चाहते हैं कि क्या कोई ऑब्जेक्ट एक वर्ग को विरासत में मिला है या एक इंटरफ़ेस को लागू करता है, तो isऑपरेटर एक बूलियन परिणाम देगा:

bool isCompatibleType = (o is BaseType || o is IInterface);

यदि आप अपने परीक्षण के बाद विरासत में मिले वर्ग या कार्यान्वित किए गए इंटरफ़ेस का उपयोग करना चाहते हैं, तो asऑपरेटर एक सुरक्षित कलाकारों का प्रदर्शन करेगा, जो विरासत में मिला वर्ग या कार्यान्वित इंटरफ़ेस का संदर्भ लौटाएगा यदि संगत या अशक्त न हो तो:

BaseType b = o as BaseType; // Null if d does not inherit from BaseType.

IInterface i = o as IInterface; // Null if d does not implement IInterface.

यदि आपके पास केवल प्रकार है T, तो @ nikeee के उत्तर का उपयोग करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.