Недопустимый литой из системы.Типа 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
на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); }
для Выше я мог бы просто написать 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 the
DefaultToTypeextracted
используя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 })); }
С другой стороны, приведение реализуется самим классом Nullable, и определение:
public static implicit operator T?(T value) { return new T?(value); } public static explicit operator T(T? value) { return value.Value; }