अमान्य सिस्टम 'System.Int32' से 'System.Nullable`1 [[System.Int32, mscorlib]]


81
Type t = typeof(int?); //will get this dynamically
object val = 5; //will get this dynamically
object nVal = Convert.ChangeType(val, t);//getting exception here

मुझे उपरोक्त कोड में InvalidCastException मिल रही है। ऊपर के लिए मैं बस लिख सकता था int? nVal = val, लेकिन उपरोक्त कोड गतिशील रूप से निष्पादित हो रहा है।

मुझे एक वस्तु (यहाँ वैल) में लिपटे हुए एक मान (गैर अशक्त प्रकार जैसे इंट, फ्लोट, इत्यादि) मिल रहा है, और मुझे इसे किसी अन्य प्रकार के लिए कास्टिंग करके किसी अन्य ऑब्जेक्ट में सहेजना होगा (जो कि अशक्त संस्करण नहीं हो सकता है या नहीं कर सकता है) इसके)। कब

अमान्य सिस्टम 'System.Int32' से 'System.Nullable`1 [[System.Int32, mscorlib, संस्करण = 4.0.0.0, संस्कृति = तटस्थ, PublicKeyToken = b77a5c5619349089]]'।

एक int, परिवर्तनीय / टाइप-कास्टेबल होना चाहिए nullable int, यहाँ क्या समस्या है?


मुझे लगता है कि शायद coz Nullable<T>लागू नहीं होता हैIConvertible
V4Vendetta

2
यह बल्कि मौलिक है। अशक्त विशेष है, जब आप इसे एक वस्तु में रखते हैं तो यह या तो शून्य हो जाता है या मूल्य प्रकार का एक बॉक्सिंग मूल्य बन जाता है। तो एक int के लिए पूछ रहे हो? एक वस्तु में संग्रहीत सिर्फ मतलब नहीं है। सिर्फ int के लिए पूछें।
हंस पैसेंट

जवाबों:


143

आपको Nullable.GetUnderlyingTypeअंतर्निहित प्रकार प्राप्त करने के लिए उपयोग करना होगा Nullable

इस विधि मैं उपयोग की सीमा को पार करने के लिए है ChangeTypeके लिएNullable

public static T ChangeType<T>(object value) 
{
   var t = typeof(T);

   if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
   {
       if (value == null) 
       { 
           return default(T); 
       }

       t = Nullable.GetUnderlyingType(t);
   }

   return (T)Convert.ChangeType(value, t);
}

गैर सामान्य विधि:

public static object ChangeType(object value, Type conversion) 
{
   var t = conversion;

   if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
   {
       if (value == null) 
       { 
           return null; 
       }

       t = Nullable.GetUnderlyingType(t);
   }

   return Convert.ChangeType(value, t);
}

उपयोगकर्ता को आपकी विधि के लिए, मुझे कुछ करने की आवश्यकता होगी:, object nVal = ChangeType<int?>(val)यहाँ मुझे जेनेरिक तर्क (T) के बारे में विधि बताने की आवश्यकता है, लेकिन मेरे पास t(या टाइपऑफ़ (डेटा टाइप)) है। मैं अपने परिदृश्य में आपके ChangeType विधि को कैसे कहूंगा?
बृज

1
गैर सामान्य संस्करण जोड़ा गया। देखें कि क्या यह मदद करता है।
gzaxx

पर संकलन त्रुटि हो रही default(conversion)है, समान मुद्दा लगता है।
बृज

सावधान @gzaxx के रूप return nullमें ही नहीं है default(T)। यदि आप संरचना के साथ काम कर रहे हैं तो वे पूरी तरह से अलग चीजें हैं।
एलेक्स

गैर सामान्य संस्करण बॉक्स संरचना और आदिम प्रकार (जैसा कि यह लेता है और वस्तु लौटाता है) को लौटाता है, इसलिए अशक्त लौटना वैध है। कार्यों को कॉल करने वाले किसी को भी इसे स्वयं संभालना होगा।
gzaxx

9

ऊपर के लिए मैं बस int लिख सकता है? nVal = घाटी

वास्तव में, आप ऐसा नहीं कर सकते। से कोई अंतर्निहित रूपांतरण नहीं objectहै Nullable<int>। लेकिन वहाँ है से एक अंतर्निहित रूपांतरण intकरने के लिए Nullable<int>ताकि आप यह लिख सकते हैं:

int? unVal = (int)val;

आप Nullable.GetUnderlyingTypeविधि का उपयोग कर सकते हैं ।

निर्दिष्ट अशक्त प्रकार के अंतर्निहित प्रकार के तर्क को लौटाता है ।

एक सामान्य प्रकार की परिभाषा एक प्रकार की घोषणा है, जैसे कि नलबल, जिसमें एक प्रकार का पैरामीटर सूची होता है, और प्रकार पैरामीटर सूची एक या अधिक प्रकार के मापदंडों की घोषणा करती है। एक बंद जेनेरिक प्रकार एक प्रकार की घोषणा है जहां एक विशेष प्रकार एक प्रकार के पैरामीटर के लिए निर्दिष्ट किया जाता है।

Type t = typeof(int?); //will get this dynamically
Type u = Nullable.GetUnderlyingType(t);
object val = 5; //will get this dynamically
object nVal = Convert.ChangeType(val, u);// nVal will be 5

यहाँ ए DEMO


2

मुझे लगता है कि मुझे समझाना चाहिए कि फ़ंक्शन क्यों काम नहीं करता है:

1- अपवाद को फेंकने वाली रेखा इस प्रकार है:

throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", new object[]
  {
    value.GetType().FullName, 
    targetType.FullName
    }));

वास्तव में अरेंज में फंक्शन सर्च में Convert.ConvertTypes उसके बाद यह देखता है कि क्या टैगर एक Enum है और कुछ नहीं मिलने पर यह ऊपर दिए गए अपवाद को फेंक देता है।

2- Convert.ConvertTypes को इस प्रकार शुरू किया गया है:

Convert.ConvertTypes = new RuntimeType[]
   {
      (RuntimeType)typeof(Empty), 
      (RuntimeType)typeof(object), 
      (RuntimeType)typeof(DBNull), 
      (RuntimeType)typeof(bool), 
      (RuntimeType)typeof(char), 
      (RuntimeType)typeof(sbyte), 
      (RuntimeType)typeof(byte), 
      (RuntimeType)typeof(short), 
      (RuntimeType)typeof(ushort), 
      (RuntimeType)typeof(int), 
      (RuntimeType)typeof(uint), 
      (RuntimeType)typeof(long), 
      (RuntimeType)typeof(ulong), 
      (RuntimeType)typeof(float), 
      (RuntimeType)typeof(double), 
      (RuntimeType)typeof(decimal), 
      (RuntimeType)typeof(DateTime), 
      (RuntimeType)typeof(object), 
      (RuntimeType)typeof(string)
   };

इसलिए चूंकि int?ConvertTypes एरे में नहीं है और एनम अपवाद नहीं है।

तो फिर से शुरू, समारोह के लिए Convert.ChnageType आपके पास काम करने के लिए:

  1. परिवर्तित होने वाली वस्तु IConvertible है

  2. लक्ष्य प्रकार ConvertTypes के भीतर है और न Emptyही DBNull(फेंक अपवाद के साथ उन दोनों पर एक खोज परीक्षण है)

यह व्यवहार वजह से है int(और अन्य सभी डिफ़ॉल्ट प्रकार) का उपयोग करता Convert.DefaultToTypeIConvertibale.ToType रूप implementation. and here is the code of theDefaultToType extractedका उपयोग करILSpy

internal static object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
{
    if (targetType == null)
    {
        throw new ArgumentNullException("targetType");
    }
    RuntimeType left = targetType as RuntimeType;
    if (left != null)
    {
        if (value.GetType() == targetType)
        {
            return value;
        }
        if (left == Convert.ConvertTypes[3])
        {
            return value.ToBoolean(provider);
        }
        if (left == Convert.ConvertTypes[4])
        {
            return value.ToChar(provider);
        }
        if (left == Convert.ConvertTypes[5])
        {
            return value.ToSByte(provider);
        }
        if (left == Convert.ConvertTypes[6])
        {
            return value.ToByte(provider);
        }
        if (left == Convert.ConvertTypes[7])
        {
            return value.ToInt16(provider);
        }
        if (left == Convert.ConvertTypes[8])
        {
            return value.ToUInt16(provider);
        }
        if (left == Convert.ConvertTypes[9])
        {
            return value.ToInt32(provider);
        }
        if (left == Convert.ConvertTypes[10])
        {
            return value.ToUInt32(provider);
        }
        if (left == Convert.ConvertTypes[11])
        {
            return value.ToInt64(provider);
        }
        if (left == Convert.ConvertTypes[12])
        {
            return value.ToUInt64(provider);
        }
        if (left == Convert.ConvertTypes[13])
        {
            return value.ToSingle(provider);
        }
        if (left == Convert.ConvertTypes[14])
        {
            return value.ToDouble(provider);
        }
        if (left == Convert.ConvertTypes[15])
        {
            return value.ToDecimal(provider);
        }
        if (left == Convert.ConvertTypes[16])
        {
            return value.ToDateTime(provider);
        }
        if (left == Convert.ConvertTypes[18])
        {
            return value.ToString(provider);
        }
        if (left == Convert.ConvertTypes[1])
        {
            return value;
        }
        if (left == Convert.EnumType)
        {
            return (Enum)value;
        }
        if (left == Convert.ConvertTypes[2])
        {
            throw new InvalidCastException(Environment.GetResourceString("InvalidCast_DBNull"));
        }
        if (left == Convert.ConvertTypes[0])
        {
            throw new InvalidCastException(Environment.GetResourceString("InvalidCast_Empty"));
        }
    }
    throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", new object[]
    {
        value.GetType().FullName, 
        targetType.FullName
    }));
}

दूसरे हाथ में कलाकारों को अशक्त वर्ग द्वारा ही लागू किया जाता है और परिभाषा है:

public static implicit operator T?(T value)
{
    return new T?(value);
}
public static explicit operator T(T? value)
{
    return value.Value;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.