Convert Object to int
2011-07-14 23:14 一一九九 阅读(2341) 评论(0) 编辑 收藏 举报在调试代码的时候碰到了这样的一行代码:
int a = (int)(Object(double));
此时报错,表明是InvalideCastException。
当时表示很奇怪:
为什么
int a = (int)(doble type)) 能够通过呢?
网上搜了一下,StackOverFlow上有个帖子:
http://stackoverflow.com/questions/745172/better-way-to-cast-object-to-int
解释如下:
You have several options:
(int)
— Cast operator. Works if the object already is an integer at some level in the inheritance hierarchy or if there is an implicit conversion defined.
int.Parse()/int.TryParse()
— For converting from a string of unknown format.
int.ParseExact()/int.TryParseExact()
— For converting from a string in a specific format
Convert.ToInt32()
— For converting an object of unknown type. It will use an explicit and implicit conversion or IConvertible implementation if any are defined.
as int?
— Note the "?". Theas
operator is only for reference types, and so I used "?" to signify aNullable<int>
. The "as
" operator works likeConvert.To____()
, but thinkTryParse()
rather thanParse()
: it returnsnull
rather than throwing an exception if the conversion fails.Of these, I would prefer
(int)
if the object really is just a boxed integer. Otherwise useConvert.ToInt32()
in this case.Note that this is a very general answer: I want to throw some attention to Darren Clark's response because I think it does a good job addressing the specifics here, but came in late and wasn't voted as well yet. He gets my vote for "accepted answer", anyway, for also recommending (int), for pointing out that if it fails
(int)(short)
might work instead, and for recommending you check your debugger to find out the actual runtime type.edited Jun 6 '09 at 0:00
community wiki
The cast (int) myobject should just work.
If that gives you an invalid cast exception then it is probably because the variant type isn't VT_I4. My bet is that a variant with VT_I4 is converted into a boxed int, VT_I2 into a boxed short, etc.
When doing a cast on a boxed value type it is only valid to cast it to the type boxed. Foe example, if the returned variant is actually a VT_I2 then (int) (short) myObject should work.
Easiest way to find out is to inspect the returned object and take a look at its type in the debugger. Also make sure that in the interop assembly you have the return value marked with MarshalAs(UnmanagedType.Struct)
answered Apr 13 '09 at 20:13
Darren Clark
87529
官方的链接:http://msdn.microsoft.com/en-us/library/ms173105.aspx
However, you might sometimes need to copy a value into a variable or method parameter of another type. For example, you might have an integer variable that you need to pass to a method whose parameter is typed as double. Or you might need to assign a class variable to a variable of an interface type. These kinds of operations are called type conversions. In C#, you can perform the following kinds of conversions:
Implicit conversions: No special syntax is required because the conversion is type safe and no data will be lost. Examples include conversions from smaller to larger integral types, and conversions from derived classes to base classes.
Explicit conversions (casts): Explicit conversions require a cast operator. Casting is required when information might be lost in the conversion, or when the conversion might not succeed for other reasons. Typical examples include numeric conversion to a type that has less precision or a smaller range, and conversion of a base-class instance to a derived class.
User-defined conversions: User-defined conversions are performed by special methods that you can define to enable explicit and implicit conversions between custom types that do not have a base class–derived class relationship. For more information, see Conversion Operators (C# Programming Guide).
Conversions with helper classes: To convert between non-compatible types, such as integers and System.DateTime objects, or hexadecimal strings and byte arrays, you can use the System.BitConverter class, the System.Convert class, and the Parse methods of the built-in numeric types, such as Int32.Parse. For more information, see How to: Convert a byte Array to an int (C# Programming Guide), How to: Convert a string to an int (C# Programming Guide), and How to: Convert Between Hexadecimal Strings and Numeric Types (C# Programming Guide).
Conversion Operators (C# Programming Guide)
http://msdn.microsoft.com/en-us/library/09479473.aspx
C# enables programmers to declare conversions on classes or structs so that classes or structs can be converted to and/or from other classes or structs, or basic types. Conversions are defined like operators and are named for the type to which they convert. Either the type of the argument to be converted, or the type of the result of the conversion, but not both, must be the containing type.
class SampleClass
{
public static explicit operator SampleClass(int i)
{
SampleClass temp = new SampleClass();
// code to convert from int to SampleClass...
return temp;
}
}
Conversion operators have the following properties:
Conversions declared as implicit occur automatically when it is required.
Conversions declared as explicit require a cast to be called.
All conversions must be declared as static.
在这里提供了一个关于BaseType和Object之间转换的,也可以简要的说明:
http://www.cnblogs.com/kwklover/archive/2006/01/12/316309.html
在通常情况,object转int都会使用.net framework的Convert.ToInt32或者Int32.Parse()函数,但这不是最高效的方式,下面的两个方案不错
MS给出的答案:
public static ToInt32(object value)
{
if(value != null)
{
return ((IConvertible)value).ToInt32(null);
}
return 0;
}
这种做法很OO,很优雅,但不能转换像"123.4"这样的数字字符,有一定缺陷;
另外一种是CSDN上的一位高手提供的:
static int ToInt(object o)
{
if (o is int)
return (int)o;
else if (o is short)
return (int)(short)o;
else if (o is byte)
return (int)(byte)o;
else if (o is long)
return (int)(long)o;
else if (o is double)
return (int)(double)o;
else if (o is float)
return (int)(float)o;
else if (o is decimal)
return (int)(decimal)o;
else if (o is uint)
return (int)(uint)o;
else if (o is ushort)
return (int)(ushort)o;
else if (o is ulong)
return (int)(ulong)o;
else if (o is sbyte)
return (int)(sbyte)o;
else
return (int)double.Parse(o.ToString());
}
这个方法就显得没那么优雅,但适应面广一些
以上摘抄至:竞赛:要求用最高的效率写出object 转 int的函数
其实就是Box和Unbox 搞得:
关键问题是因为进行了Unbox和box的操作, 而Box和UnBox操作需要在同一类型下进行。MSDN的解释如下:
Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap. Unboxing extracts the value type from the object. Boxing is implicit; unboxing is explicit. The concept of boxing and unboxing underlies the C# unified view of the type system, in which a value of any type can be treated as an object.
Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface. An unboxing operation consists of:
1. Checking the object instance to make sure that it is a boxed value of the given value type.
2. Copying the value from the instance into the value-type variable.
当类型不一致时会引发异常: For the unboxing of value types to succeed at run time, the item being unboxed must be a reference to an object that was previously created by boxing an instance of that value type. Attempting to unbox null causes a NullReferenceException. Attempting to unbox a reference to an incompatible value type causes an InvalidCastException.
比如说如下的一段话:
double f = 55.366;
int e = (int)f;
object fo = f;
int e0 = (int)fo;
得到的是IL是
IL_0001: ldc.r8 55.366
IL_000a:
stloc.0 IL_000b:
ldloc.0 IL_000c:
conv.i4 IL_000d:
stloc.1 IL_000e:
ldloc.0 IL_000f: box [mscorlib]System.Double
IL_0014: stloc.2 IL_0015: ldloc.2
//看这里执行时Box操作而不是conv操作 IL_0016: unbox.any [mscorlib]System.Int32 IL_001b: stloc.3