代码改变世界

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 "?". The as operator is only for reference types, and so I used "?" to signify a Nullable<int>. The "as" operator works like Convert.To____(), but think TryParse() rather than Parse(): it returns null 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 use Convert.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.

link|edit

edited Jun 6 '09 at 0:00

community wiki

8 revs
Joel Coehoorn

 

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)

link|edit

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:

 

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 Overview


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