C# 从“System.Int32”到“System.Nullable”1[[System.Int32, mscorlib]] 的无效转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18015425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Int32, mscorlib]]
提问by Brij
Type t = typeof(int?); //will get this dynamically
object val = 5; //will get this dynamically
object nVal = Convert.ChangeType(val, t);//getting exception here
I am getting InvalidCastException in above code. For above I could simply write int? nVal = val
, but above code is executing dynamically.
我在上面的代码中收到 InvalidCastException。对于上面我可以简单地写int? nVal = val
,但上面的代码是动态执行的。
I am getting a value(of non nullable type like int, float, etc) wrapped up in an object (here val), and I have to save it to another object by casting it to another type(which can or cannot be nullable version of it). When
我得到一个值(非空类型,如 int、float 等)包裹在一个对象(这里是 val)中,我必须通过将它转换为另一种类型(可以或不能为可空版本)来将它保存到另一个对象其中)。什么时候
Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
从“System.Int32”到“System.Nullable”1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'的无效转换。
An int
, should be convertible/type-castable to nullable int
, what is the issue here ?
An int
, 应该可以转换/类型转换为nullable int
,这里有什么问题?
采纳答案by gzaxx
You have to use Nullable.GetUnderlyingType
to get underlying type of Nullable
.
您必须使用Nullable.GetUnderlyingType
来获取Nullable
.
This is the method I use to overcome limitation of ChangeType
for Nullable
这是我用来克服ChangeType
for限制的方法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);
}
non generic method:
非通用方法:
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);
}
回答by Soner G?nül
For above I could simply write int? nVal = val
对于上面我可以简单地写 int? nVal = val
Actually, you can't do that either. There is no implicit conversion from object
to Nullable<int>
. But there isan implicit conversion from int
to Nullable<int>
so you can write this:
事实上,你也不能那样做。没有从object
到 的隐式转换Nullable<int>
。但是,是从隐式转换int
到Nullable<int>
,所以你可以这样写:
int? unVal = (int)val;
You can use Nullable.GetUnderlyingType
method.
您可以使用Nullable.GetUnderlyingType
方法。
Returns the underlying type argumentof the specified nullable type.
A generic type definition is a type declaration, such as Nullable, that contains a type parameter list, and the type parameter list declares one or more type parameters. A closed generic type is a type declaration where a particular type is specified for a type parameter.
返回指定的可为空类型的基础类型参数。
泛型类型定义是一种类型声明,例如 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
Here's a DEMO
.
这是一个DEMO
.
回答by Swift
I think I should explain why the function does not work:
我想我应该解释为什么该功能不起作用:
1- The line that throw the exception is as follows:
1- 抛出异常的行如下:
throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", new object[]
{
value.GetType().FullName,
targetType.FullName
}));
in fact the function search in the array Convert.ConvertTypes after that it see if the targer is an Enum and when nothing is found it throw the exception above.
实际上,函数在数组 Convert.ConvertTypes 中搜索之后,它会查看目标是否是 Enum,当没有找到任何东西时,它会抛出上面的异常。
2- the Convert.ConvertTypes is initialized as:
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)
};
So since the int?
is not in the ConvertTypes array and not an Enum the exception is thrown.
因此,由于int?
不在 ConvertTypes 数组中,也不是在 Enum 中,因此抛出异常。
So to resume, for the function Convert.ChnageType to work you have:
所以要继续,为了让函数 Convert.ChnageType 工作,你有:
The object to be converted is IConvertible
The target type is within the ConvertTypes and not
Empty
norDBNull
(There is an explict test on those two with throw exception)
要转换的对象是 IConvertible
目标类型在 ConvertTypes 之内,而不是
Empty
或DBNull
(有对这两个抛出异常的显式测试)
This behaviour is because int
(and all other default types) uses Convert.DefaultToType
as IConvertibale.ToType implementation. and here is the code of the
DefaultToTypeextracted
using ILSpy
这种行为是因为int
(和所有其他默认类型)使用Convert.DefaultToType
作为 IConvertibale.ToType 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
}));
}
in other hand the cast is implemented by Nullable class itself and the definition is:
另一方面,转换是由 Nullable 类本身实现的,定义是:
public static implicit operator T?(T value)
{
return new T?(value);
}
public static explicit operator T(T? value)
{
return value.Value;
}