2011-09-21 13 views
8

मैं परीक्षण करने के लिए एक दिया object एक दिया Type लिए डाली जा सकती है कि क्या चाहते हो के साथ आपरेशन 'के रूप में' प्रदर्शन करने के लिए।सी #: कैसे एक प्रकार

इस परिदृश्य में, मैं एक वस्तु है, और Type का प्रतिनिधित्व किस प्रकार मैं करने के लिए इसे कास्ट करना चाहते हैं:

public function FooBar(..., object data, Type expected) { 
    ... 
    var unboxedData = ? 
    if (unboxedData == null) { 
     .... 
    } 
    ... 
} 

मैं कैसे प्रकार type का प्रतिनिधित्व करता है के लिए data डाली कर सकते हैं?

मूल रूप से, मैं ऐसा करना चाहते हैं:

var unboxedData = data as Type; 

... लेकिन बेशक आप एक as बयान के साथ Type उपयोग नहीं कर सकते की है, तो मैं क्या करूँ?

+4

आप * परीक्षण * करना चाहते हैं, या आप * कास्ट * करना चाहते हैं? – CesarGon

उत्तर

6

संपादित करें 2: मैं यह कहने जा रहा हूं कि प्रतिबिंब या जेनेरिक के बिना यह संभव नहीं है। प्रतिबिंब के साथ, आपके पास कोई संकलन-समय जांच नहीं है और ऑब्जेक्ट के आगे कॉल विधियों/गुणों के लिए प्रतिबिंब (या dynamic) का उपयोग करना चाहिए। जेनेरिक के साथ, आप अकेले वहां जाने के लिए टाइप ऑब्जेक्ट का उपयोग नहीं कर सकते हैं। अपना चयन ले लो। जेनेरिकों को अनुमति देने के लिए अपने कॉलिंग कोड को दोबारा बदलना संभव है?


हैं की अनुमति दी, इस और अधिक आसानी से एक सामान्य विधि के साथ संभाला जा सकता है:

public resultType FooBar<T>(..., object data) { 
    ... 
    T unboxedData = (T)data; 
    ... 
} 

संपादित करें: इसके अलावा, आप data as T उपयोग कर सकते हैं अगर आप where T : class की एक सामान्य प्रकार बाधा शामिल हैं:

public something FooBar<T>(..., object data) 
    where T : class 
{ 
    ... 
    T unboxedData = data as T; 
    if (unboxedData == null) { 
     ... 
    } 
    ... 
} 
+2

और क्या होगा यदि यह IConvertible लागू नहीं करता है? – IEHaterNumber1

+0

असल में, मेरे पास 'कनवर्ट। चेंजटाइप' था क्योंकि मुझे उस अनावश्यक कॉल के बिना सीधे डालने का प्रयास करते समय संकलक त्रुटियां मिल रही थीं। मैंने अभी परीक्षण किया और '(टी) डेटा 'ठीक काम करता है, इसलिए मैंने इसे बदल दिया। यदि आप 'जहां टी: कक्षा' की सामान्य प्रकार की बाधा शामिल करते हैं तो आप 'टी के रूप में डेटा भी कर सकते हैं। – mellamokb

+0

यह समस्या को हल करने के लिए प्रतीत नहीं होता है, क्योंकि वह एक प्रकार चर के साथ शुरू होता है। देखें: http://stackoverflow.com/questions/266115/pass-an-instantiated-system-type-as-a-type-parameter-for-a-generic-class आप टाइप के उदाहरण में पास नहीं कर सकते एक सामान्य – deepee1

3

... लेकिन निश्चित रूप से आप टाइप के साथ टाइप का उपयोग नहीं कर सकते टेटमेंट, तो मैं क्या करूँ?

मोर महत्वपूर्ण रूप से, आप var इस तरह से उपयोग नहीं कर सकते हैं। तो यहां हासिल करने के लिए कुछ भी नहीं है।

आप कर सकते हैं परीक्षण अगर यह

if (expected.IsInstanceOfType(data)) 

साथ सही प्रकार है लेकिन फिर तुम अब भी data पर गुण या तरीकों का उपयोग करने में किसी भी सभ्य कोड नहीं लिख सकते हैं।

2

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

Hexagon hex2 = frank as Hexagon; 

if (hex2 == null) 
    Console.WriteLine("Sorry, frank is not a Hexagon..."); 

इसके अलावा: निम्नलिखित पर विचार करें। कीवर्ड के विपरीत, हालांकि, कीवर्ड एक संक्षिप्त संदर्भ के बजाय झूठा रिटर्न देता है, यदि प्रकार असंगत हैं।

if (emp is SalesPerson) 
{ 
    Console.WriteLine("{0} made {1} sale(s)!", emp.Name, 
               ((SalesPerson)emp).SalesNumber); 
} 
+2

आप कहीं भी 'टाइप' का उपयोग नहीं कर रहे हैं। आप स्पष्ट रूप से प्रकार को परिभाषित कर रहे हैं। – IEHaterNumber1

+1

अच्छी तरह से आप 'var' का उपयोग कर रहे हैं, इसलिए आपको" as "ऑपरेटर का उपयोग करने की आवश्यकता नहीं है। इसके अलावा, यदि आप असाइन करना चाहते हैं, तो टाइप बी के एक चर को टाइप करें जो ए से विरासत में मिलता है, फिर आप 'टाइप ए = टाइप बी टाइप ए' के ​​रूप में उपयोग कर सकते हैं। –

+2

@ पंकज मुझे लगता है कि आप गलत समझते हैं: ओपी [.NET टाइप क्लास] (http://msdn.microsoft.com/en-us/library/system.type.aspx) के उदाहरण में गुज़र रहा है, जो एक है किसी दिए गए प्रकार का मेटाडाटा प्रतिनिधित्व। ओपी सोच रहा है कि किसी ऑब्जेक्ट के प्रकार को * टाइप 'द्वारा दर्शाए गए प्रकार के प्रकार की तुलना कैसे करें। –

1
if (data.GetType() == t || data.GetType().IsSubclassOf(t)) 
{ 
//do your thing 
} 

आप बताना चाहिए अगर यह वास्तव में है या का एक उपवर्ग (इसलिए यह यह करने के लिए में डाली जा सकती है)।

0

ठीक है, मैं somthing पाया चारों ओर देख ... How to check if implicit or explicit cast exists?

सावधान रहें, मैं इसे बहुत परीक्षण नहीं दिया है, लेकिन एक ही नज़र में यह होनहार हो रहा है।

static bool isConvertableTo(object o, Type t) 
    { 
     try 
     { 
      var expr = Expression.Constant(o); 
      var res = Expression.Convert(expr, t); 
      return true; 
     } 
     catch { } 
     return false; 
    } 

एक ही दृष्टिकोण के साथ एक और उपयोगी लिंक: Checking if a type supports an implicit or explicit type conversion to another type with .NET

1

यह सुंदर मुश्किल है एक बड़ा नकारात्मक है कि यह अपवाद फेंकता है तो यह है कि यह परिवर्तित नहीं कर सकते है। समस्या यह है कि var का मतलब "संस्करण" नहीं है। यह अस्थायी प्लेसहोल्डर की तरह अधिक कार्य करता है कि अभिव्यक्ति से प्रकार की जानकारी अनुमानित होने के बाद सी # वास्तविक प्रकार के साथ भर जाता है। unboxedData अभी भी एक दृढ़ता से टाइप किया गया चर है। यह सिर्फ संकलक आप को स्पष्ट रूप से निर्दिष्ट करने के बजाय प्रकार को समझने की कोशिश कर रहा है। यह ध्यान रखना महत्वपूर्ण है कि टाइपिंग अभी भी संकलित समय पर चल रही है और रनटाइम नहीं है।

यदि आप रनटाइम पर किसी ऑब्जेक्ट को गतिशील रूप से डालना चाहते हैं तो आप var या किसी अन्य ठोस प्रकार विनिर्देशक का उपयोग करने में सक्षम नहीं होंगे।

आपके विकल्प दो संभावित घोषणाओं में से एक तक सीमित हैं:

  • वस्तु
  • गतिशील

मैं क्या सोचते आप मुझे लगता है dynamic है unboxedData साथ क्या करना चाहते के आधार पर जिस मार्ग पर आप जाना चाहते हैं क्योंकि यह आपको Type पर किसी भी विधि को कॉल करने की अनुमति देगा।

तो मैं यहां आया हूं।

public void FooBar(object value, Type expected) 
{ 
    dynamic unboxedData = expected.FromObject(value); 
    unboxedData.CallSomeMethodDefinedInTheTargetType(); // This will work. 
} 

इसके लिए निम्न विस्तार विधि की आवश्यकता है।

public static class TypeExtension 
{ 
    public static object FromObject(this Type target, object value) 
    { 
     var convertable = value as IConvertible; 
     if (convertable != null) 
     { 
      return convertable.ToType(target, null); 
     } 
     Type type = value.GetType(); 
     if (target.IsAssignableFrom(type)) 
     { 
      return value; 
     } 
     MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public); 
     foreach (MethodInfo mi in methods) 
     { 
      if (mi.ReturnType == target) 
      { 
       try 
       { 
        return mi.Invoke(null, new object[] { value }); 
       } 
       catch (TargetInvocationException caught) 
       { 
        if (caught.InnerException != null) 
        { 
         throw caught.InnerException; 
        } 
        throw; 
       } 
      } 
     } 
     throw new InvalidCastException(); 
    } 
} 

यदि इनमें से कोई एक सत्य है तो कास्ट काम करेगा।

  • IConvertible लागू करने के लिए मूल्य को लक्षित प्रकार के लिए एक रूपांतरण पथ है।
  • लक्ष्य प्रकार को उपclasses परिवर्तित करने के लिए मूल्य।
  • परिवर्तित करने के लिए मूल्य अपनी कक्षा घोषणा में explicit conversion operator परिभाषित करता है।
+0

मैं एक उत्तर लिखने जा रहा था, लेकिन आपका बहुत बेहतर है। +1 – Davy8

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