Help: VS2003 BUG? - Boxed value types cannot be casted to custom value types

L

Laura T.

The following code is driving me so crazy, that I'm thinking it's a
"feature" or a..
....dare I say it... a BUG. I'm using VS 2003.

I've created a new value type (struct) called MyInt. MyInt has
all(?) the conversion routines necessary to convert from Int32 and string.
(see the listing at the end)

When I cast directly from a value of Int32 type, it works:

MyInt v=(MyInt)1 or
MyInt v=(MyInt)varInt32;

When I try to cast a boxed value (object returned from a function),
I get "Specified cast is not valid." System.InvalidCastException:

private object GetInt()
{
return 1
}

MyInt v=(MyInt)GetInt(); <-- Exception.


The IL code generated is the following:

..method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01
00 00 00 )
// Code size 24 (0x18)
.maxstack 1
.locals init ([0] valuetype Cast.MyInt z1,[1] valuetype Cast.MyInt z2)
IL_0000: call object Cast.Class1::NewInt()
IL_0005: unbox Cast.MyInt
IL_000a: ldobj Cast.MyInt
IL_000f: stloc.0
IL_0010: ldc.i4.2
IL_0011: call valuetype Cast.MyInt Cast.MyInt::blush:p_Explicit(int32)
IL_0016: stloc.1
IL_0017: ret
} // end of method Class1::Main

Is this something that cannot be done? I've searched everywhere but nothing
states that it cannot be done.
_OR_ am I missing something or doing something awfully wrong?

Please help me!

Laura




------- Copy and paste to a C# Console Application project ----------------

using System;

namespace Cast
{
public struct MyInt
{
private Int32 _my_int;

public MyInt(Int32 value)
{
_my_int=value;
}

public MyInt(object value)
{
_my_int=System.Convert.ToInt32(value);
}

public static explicit operator MyInt(string value)
{
return new MyInt(System.Convert.ToInt32(value));
}

public static explicit operator MyInt(Int32 value)
{
return new MyInt(value);
}
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
MyInt z1=(MyInt)NewInt();
}

private static object NewInt()
{
return 1;
}
}
}
 
C

Cowboy \(Gregory A. Beamer\) [MVP]

It deals with the fact you are casting an object to a more specific type,
from a cursory glance. If you were returning an int, you would be able to
cast:

private static int NewInt()
{
return 1;
}

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

************************************************
Think Outside the Box!
************************************************
 
J

Jon Skeet [C# MVP]

Laura T. said:
The following code is driving me so crazy, that I'm thinking it's a
"feature" or a..
...dare I say it... a BUG. I'm using VS 2003.

No, it's not a bug.
I've created a new value type (struct) called MyInt. MyInt has
all(?) the conversion routines necessary to convert from Int32 and string.
(see the listing at the end)

When I cast directly from a value of Int32 type, it works:

MyInt v=(MyInt)1 or
MyInt v=(MyInt)varInt32;

When I try to cast a boxed value (object returned from a function),
I get "Specified cast is not valid." System.InvalidCastException:

private object GetInt()
{
return 1
}

MyInt v=(MyInt)GetInt(); <-- Exception.

An unboxing cast must be to *exactly* the type which was boxed - it
can't do any conversion at the same time.

If you change your code to:

MyInt v = (MyInt)(int)GetInt();

then it'll work fine.

Is this something that cannot be done? I've searched everywhere but nothing
states that it cannot be done.

Yes it does - the C# language spec, section 11.3.2 (ECMA version):

<quote>
For an unboxing conversion to a given value-type to succeed at run-
time, the value of the source operand must be a reference to an object
that was previously created by boxing a value of that value-type.
</quote>
 
L

Laura T.

Jon Skeet said:
No, it's not a bug.
I'm glad. :)
And thanks for the quick reply. I really appreciate it.

I must admit that some examples in the C# spec made me expect that
the boxed value really was a temporary object (as in one example,
int_box()) so that there was no need to recast again, like
MyInt x=(MyInt)GetInt() became
MyInt x=new MyInt(new int_box(1)). I think that would be legal.

Thanks.

Laura
Yes it does - the C# language spec, section 11.3.2 (ECMA version):

<quote>
For an unboxing conversion to a given value-type to succeed at run-
time, the value of the source operand must be a reference to an object
that was previously created by boxing a value of that value-type.
</quote>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top