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),我必须将它保存到另一个对象中,方法是将它转换为另一个类型(它可以或者不能是它的可空版本)。什么时候
从“System.Int32”到“System.Nullable`1[System.Int32,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]的强制转换无效。
int
,应该是可转换/类型为nullable int
的,这里的问题是什么?
发布于 2013-08-02 11:19:09
您必须使用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);
}
发布于 2013-08-02 11:16:07
因为上面我可以简单地写int?nVal = val
实际上,你也不能这么做。不存在从object
到Nullable<int>
的隐式转换。但是有一个从int
到Nullable<int>
的隐式转换,所以您可以这样写:
int? unVal = (int)val;
您可以使用Nullable.GetUnderlyingType
方法。
返回指定可空类型的基础类型参数。 泛型类型定义是包含类型参数列表的类型声明(如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
这是一个DEMO
。
发布于 2013-08-02 11:40:58
我想我应该解释一下为什么这个功能不起作用:
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数组中,而不是Enum中,因此抛出异常。
因此,若要继续工作,Convert.ChnageType函数必须具备以下功能:
Empty
或DBNull
中(除了抛出异常,这两种类型都有明确的测试)这种行为是因为int
(以及所有其他默认类型)使用Convert.DefaultToType
作为使用ILSpy
的IConvertibale.ToType implementation. and here is the code of the
DefaultToTypeextracted
。
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;
}
https://stackoverflow.com/questions/18015425
复制相似问题