Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
यह एक त्रुटि है। C # में टाइपऑफ़ ऑपरेटर केवल टाइप नाम ले सकता है, ऑब्जेक्ट नहीं।
if (obj1.GetType() == typeof(int))
// Some code here
यह काम करेगा, लेकिन शायद वैसा नहीं जैसा आप उम्मीद करेंगे। मूल्य प्रकारों के लिए, जैसा कि आपने यहां दिखाया है, यह स्वीकार्य है, लेकिन संदर्भ प्रकारों के लिए, यह केवल तभी सही होगा जब प्रकार सटीक एक ही प्रकार का था, न कि वंशानुगत पदानुक्रम में कुछ और। उदाहरण के लिए:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
यह प्रिंट होगा "o is something else"
, क्योंकि प्रकार o
है Dog
, नहीं Animal
। आप यह कार्य कर सकते हैं, हालाँकि, यदि आप कक्षा की IsAssignableFrom
पद्धति का उपयोग करते हैं Type
।
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
यह तकनीक अभी भी एक बड़ी समस्या है। यदि आपका चर शून्य है, तो कॉल GetType()
NullReferenceException को फेंक देगा। तो यह सही ढंग से काम करने के लिए, आप करेंगे:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
इसके साथ, आपके पास is
कीवर्ड का समान व्यवहार है । इसलिए, यदि आप चाहते हैं कि यह व्यवहार है, तो आपको is
कीवर्ड का उपयोग करना चाहिए , जो अधिक पठनीय और अधिक कुशल है।
if(o is Animal)
Console.WriteLine("o is an animal");
ज्यादातर मामलों में, हालांकि, is
कीवर्ड अभी भी वही नहीं है जो आप वास्तव में चाहते हैं, क्योंकि यह आमतौर पर यह जानने के लिए पर्याप्त नहीं है कि एक वस्तु एक निश्चित प्रकार की है। आमतौर पर, आप वास्तव में उस वस्तु को उस प्रकार के उदाहरण के रूप में उपयोग करना चाहते हैं , जिसके लिए उसे भी कास्टिंग की आवश्यकता होती है। और इसलिए आप अपने आप को इस तरह कोड लिख सकते हैं:
if(o is Animal)
((Animal)o).Speak();
लेकिन इससे सीएलआर दो बार ऑब्जेक्ट के प्रकार की जांच करता है। यह is
ऑपरेटर को संतुष्ट करने के लिए एक बार इसकी जांच करेगा , और यदि o
वास्तव में ए है Animal
, तो हम इसे कास्ट को मान्य करने के लिए फिर से जांच करते हैं।
इसके बजाय ऐसा करना अधिक कुशल है:
Animal a = o as Animal;
if(a != null)
a.Speak();
as
ऑपरेटर एक डाली कि एक अपवाद अगर यह विफल रहता है, बजाय लौटने फेंक नहीं होगा null
। इस तरह, सीएलआर वस्तु के प्रकार को एक बार जांचता है, और उसके बाद, हमें बस एक शून्य जांच करने की आवश्यकता होती है, जो अधिक कुशल है।
लेकिन सावधान रहना: कई लोगों के साथ एक जाल में गिर जाते हैं as
। क्योंकि यह अपवादों को नहीं फेंकता है, कुछ लोग इसे "सुरक्षित" कास्ट के रूप में सोचते हैं, और वे इसे विशेष रूप से उपयोग करते हैं, नियमित रूप से चमचमाते हुए। यह इस तरह त्रुटियों की ओर जाता है:
(o as Animal).Speak();
इस मामले में, डेवलपर स्पष्ट रूप से यह सोचते है कि o
होगा हमेशा एक हो Animal
, और जब तक उनकी धारणा सही है, तो सब कुछ ठीक काम करता है। लेकिन अगर वे गलत हैं, तो वे जो यहां समाप्त करते हैं वह एक है NullReferenceException
। एक नियमित कलाकारों के साथ, वे एक मिल गया होताInvalidCastException
बदले , जो समस्या को अधिक सही ढंग से पहचानता था।
कभी-कभी, इस बग को ढूंढना मुश्किल हो सकता है:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
यह एक और मामला है जहां डेवलपर स्पष्ट रूप से हर बार o
होने की उम्मीद कर रहा है Animal
, लेकिन यह स्पष्ट नहीं है कि निर्माता, जहां as
कलाकारों का उपयोग किया जाता है। यह तब तक स्पष्ट नहीं है जब तक आप उस Interact
विधि से नहीं मिलते हैं , जहां animal
क्षेत्र को सकारात्मक रूप से सौंपा जाना अपेक्षित है। इस मामले में, न केवल आप एक भ्रामक अपवाद के साथ समाप्त होते हैं, लेकिन यह तब तक नहीं फेंका जाता है जब तक कि वास्तविक त्रुटि होने पर संभावित रूप से बहुत बाद में।
संक्षेप में:
यदि आपको केवल यह जानना है कि वस्तु किसी प्रकार की है या नहीं, तो उपयोग करें is
।
यदि आपको किसी निश्चित प्रकार के उदाहरण के रूप में किसी वस्तु का इलाज करने की आवश्यकता है, लेकिन आप यह नहीं जानते हैं कि वस्तु उस प्रकार की होगी, तो उपयोग करें as
और जांच करें null
।
यदि आपको एक निश्चित प्रकार के उदाहरण के रूप में एक वस्तु का इलाज करने की आवश्यकता है, और वस्तु को उस प्रकार का माना जाता है, तो एक नियमित कलाकारों का उपयोग करें।
as
!