Недопустимый литой из системы.Типа int32' к 'системе.И Nullable`1[[Система.Типа int32, библиотеку mscorlib]]
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, но выше код выполняется динамически.
Я получаю значение (ненулевого типа, например int, float и т. д.), завернутое в объект (здесь val), и я должен сохранить его в другой объект, приведя его к другому типу(который может или не может быть его нулевой версией). Когда
недопустимый литой из 'системы.Типа int32' к 'системе.И Nullable`1[[Система.Типа int32, mscorlib, Version=4.0.0.0, Culture=нейтральный, PublicKeyToken=b77a5c561934e089]]'.
An int, должно быть конвертируемым / тип-castable к nullable int, в чем здесь проблема ?
3 ответа:
вы должны использовать
Nullable.GetUnderlyingTypeчтобы получить базовый типNullable.это метод, который я использую, чтобы преодолеть ограничение
ChangeTypeнаNullablepublic 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); }
для Выше я мог бы просто написать int? nVal = val
на самом деле, вы тоже не можете этого сделать. Нет никакого неявного преобразования из
objectдоNullable<int>. Но там и неявное преобразование изintдоNullable<int>Так что вы можете писать так:int? unVal = (int)val;можно использовать
Nullable.GetUnderlyingTypeметод.возвращает базовый аргумент типа указанного типа nullable.
определение универсального типа-это объявление типа, например Nullable, содержит список параметров типа и список параметров типа объявляет один или несколько параметров типа. Закрытый универсальный тип объявление, в котором для параметра типа указан определенный тип.
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здесь a
DEMO.
я думаю, что я должен объяснить, почему функция не работает:
1-строка, которая вызывает исключение, выглядит следующим образом:
throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", new object[] { value.GetType().FullName, targetType.FullName }));в самом деле, функция поиска в массиве преобразования.ConvertTypes после этого он видит, является ли targer перечислением, и когда ничего не найдено, он бросает исключение выше.
2 - преобразования.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 и не является перечислением исключение.Итак, чтобы возобновить, для функции преобразования.ChnageType для работы у вас есть:
объект для преобразования является IConvertible
целевой тип находится в пределах ConvertTypes, а не
Empty, ниDBNull(есть явный тест на этих двух с исключением броска)такое поведение происходит потому, что
int(и все другие типы по умолчанию) используетConvert.DefaultToTypeкак IConvertibale.Тотипimplementation. and here is the code of theDefaultToTypeextractedиспользуяILSpyinternal 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 })); }С другой стороны, приведение реализуется самим классом Nullable, и определение:
public static implicit operator T?(T value) { return new T?(value); } public static explicit operator T(T? value) { return value.Value; }