2013-04-03 3 views
6

जब मैं किसी ऑब्जेक्ट को एक्सटेंशन विधि के माध्यम से डालने का प्रयास कर रहा हूं तो मुझे एक अजीब समस्या है। मेरे पास एक कक्षा है जहां मैं IPAddress के आसपास कुछ कार्यक्षमता लपेटता हूं।एक एक्सटेंशन विधि में स्पष्ट कास्ट का उपयोग

// Dumbed down version of class 
public sealed class PrefixLengthIPAddress 
{ 
    public static explicit operator IPAddress(PrefixLengthIPAddress address) 
    { 
     return (address != null) ? address._address : null; 
    } 

    public PrefixLengthIPAddress(IPAddress address) 
    { 
     _address = address; 
     _length = address.GetLength(); 
    } 

    private readonly ushort _length; 
    private readonly IPAddress _address; 
} 

मैं सभी कोष्ठक का स्वरूप पसंद नहीं आया वस्तु से बाहर निकालने के लिए IPAddress:

var family = prefixLengthAddress.CastAs<IPAddress>().AddressFamily; 
:

var family = ((IPAddress)prefixLengthAddress).AddressFamily; 

मैं नहीं बल्कि कुछ इस तरह करने में सक्षम हो जाएगा

ऐसा करने के लिए मैंने निम्नलिखित विस्तार विधि लिखा:

public static T CastAs<T>(this object value) where T : class 
{ 
    return (T)value; 
} 
इस के साथ दुर्भाग्य से

मैं हो रही है एक InvalidCastException:

var family = ((IPAddress)prefixLengthAddress).AddressFamily;   // Works 
var family = prefixLengthAddress.CastAs<IPAddress>().AddressFamily; // InvalidCastException 

मैं समझता हूँ कि इस विशेष मामले में मैं बस एक गेटर साथ IPAddress बेनकाब सकता है, लेकिन हम भी और अधिक जटिल स्पष्ट डाले है कि मैं करना चाहते हैं इसके साथ करो

संपादित

धन्यवाद dynamic के प्रयोग पर क्रिस सिंक्लेयर की टिप्पणी करने के लिए मैं विस्तार विधि को अद्यतन किया है की तरह लग रहे करने के लिए:

public static T CastAs<T>(this object value) 
{ 
    return (T)((dynamic)value); 
} 

वहाँ dynamic का उपयोग कर के साथ कुछ भूमि के ऊपर है, लेकिन यह तेजी से और अधिक से अधिक है मेरी जरूरतों के लिए पर्याप्त है। ऐसा लगता है कि मैंने कोशिश की सभी मूल प्रकार के कास्टिंग के साथ भी काम करना प्रतीत होता है।

+0

ठीक है, 'प्रीफिक्सलेथिप एड्रेस्रेस' का प्रकार पदानुक्रम में 'IPAddress'' से कोई संबंध नहीं है, जो समस्या का अंतिम स्रोत है। दूसरी स्थिति क्या है जिसके लिए आप इस कास्टिंग कोड का उपयोग करेंगे? टाइप बी के उदाहरण के लिए टाइप ए के उदाहरण को मनमाने ढंग से बल देने की कोशिश विफलता के लिए बाध्य है। इसके अतिरिक्त, जेनेरिक वास्तव में असंबद्ध है; इसलिए 'टी' एक 'स्ट्रिंग' हो सकता है, और कोई ऑपरेटर ओवरलोडिंग नहीं हो सकती है। मुझे संदेह है कि 'टी' के लिए 'आईपीएड्रेस' से जुड़ा हुआ भी आपके द्वारा अपेक्षित व्यवहार का नेतृत्व नहीं करेगा, और यदि यह भी हुआ, तो आपका एक्सटेंशन अन्यथा बेकार है। – Tejs

+0

मुझे बस एक्सटेंशन विधि को बेहतर दिखाना पसंद है। अगर मैंने अपनी ऑब्जेक्ट को एक स्ट्रिंग के रूप में डालने का प्रयास किया तो मैं उम्मीद करता हूं कि यह किसी भी तरह से अमान्य कैस्टएक्सप्शन को फेंक देगा। – lumberjack4

उत्तर

7

पहले नमूने में आप उपयोगकर्ता परिभाषित रूपांतरण तक पहुंच रहे हैं। यह केवल तभी उपलब्ध होता है जब कास्ट ऑपरेटर इनपुट के प्रकार को जानता है PrefixLengthAddress है। सामान्य कोड में संकलक केवल object और T टाइप करता है। इस परिदृश्य में PrefixLengthAddress पर परिभाषित रूपांतरण तक पहुंचने का कोई तरीका नहीं है।

इस परिदृश्य में आप जो कर रहे हैं वह मैपिंग बनाम कास्टिंग के करीब है क्योंकि यह वास्तव में एक नया मूल्य बना रहा है। LINQ के संदर्भ में आप Select बनाम Cast का उपयोग करना चाहेंगे।

+0

विस्तार विधि के अंदर फेंक दिया गया अपवाद संदेश "System.Net.IPAddress" टाइप करने के लिए "उपसर्ग प्रकार का ऑब्जेक्ट डालने में असमर्थ" PrefixLengthIPAddress 'है। तो इस मामले में इस प्रकार को कैसे नहीं पता? – lumberjack4

+0

@ lumberjack4 उपयोगकर्ता परिभाषित रूपांतरण केवल भाषा संकलक (इस मामले में सी #) द्वारा उपयोग किए जाते हैं। उपयोग करने के लिए प्रकार संकलन समय पर जाना जाना चाहिए। आपका देखने का रनटाइम कह रहा है कि 2 प्रकार के बीच कोई विरासत संबंध नहीं है। रनटाइम उपयोगकर्ता परिभाषित रूपांतरणों पर विचार नहीं करेगा – JaredPar

+0

लिंक 'संख्यात्मक कैसे करता है।CastIterator 'फिर काम? जब मैं उस कोड को देखो यह मेरा लगभग समान दिखता है: निजी स्थिर IEnumerable CastIterator (IEnumerable स्रोत) { foreach (स्रोत में वस्तु obj) उपज वापसी (TResult) obj; } – lumberjack4

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