Casting object to int throws InvalidCastException in C#
Asked Answered
U

3

7

I have this method:

private static Dossier PrepareDossier(List<List<object>> rawDossier)
{
    return new Dossier((int)rawDossier[0][0]);
}

When I use it I get an InvalidCastException. However, when I use Convert.ToInt32(rawDossier[0][0]) it works just fine. What is the problem?

Unsaddle answered 6/10, 2016 at 8:45 Comment(5)
What is the type of the object stored at rawDossier[0][0]? If it is for example a string containing a valid number, Convert.ToInt32() will work just fine but the cast will of course throw.Trefoil
(edited) You cannot unbox a box with one numeric type into another numeric type. Also, like @RenéVogt says, you cannot convert a reference to a string to a value type with the cast syntax.Smokestack
What does rawDossier[0][0] ?. GetType().ToString() give?Smokestack
It's a string. I actually get it from the database, and I did not know that it retrieves it as a string. Thank you all.Unsaddle
Other questions/duplicates all combining to a full answer: Why does (int)(object)10m throw “Specified cast is not valid” exception?, Cast object containing int to float results in InvalidCastException, Why can't I unbox an int as a decimal?Trunnel
A
29

The problem is that you don't cast an object to an int, you're attempting to unbox an int.

The object really has to be an int. It cannot be just anything that can be converted to an int.

So the difference is that this:

int a = (int)obj;

Really needs obj to be a boxed int, nothing else, whereas this:

int a = Convert.ToInt32(obj);

Will execute the ToInt32 method which will try to figure out what is really going on and do the right thing.

The "right thing" here is to ensure the object in question implements IConvertible and calling IConvertible.ToInt32, as is evident from the reference source:

public static int ToInt32(object value) {
    return value == null? 0: ((IConvertible)value).ToInt32(null);
}

You can see the unboxing on try roslyn:

IL_0007: unbox.any [mscorlib]System.Int32

Conclusion: The object you're trying to unbox is not an int, but it is something that can be converted to an int.

Achromaticity answered 6/10, 2016 at 8:47 Comment(0)
I
2

I would guess this is because the object in your list is not an int.

Convert.ToInt32 will convert other non-int types so works.

Check what is being passed in to the method.

Intention answered 6/10, 2016 at 8:47 Comment(0)
P
2

When you try to unbox int from an object, the boxed value should be int, otherwise you will receive an exception, while Convert.ToInt32 uses IConvertible implementation of boxed type to convert the value to int.

For example if the value which is boxed is string "100", unboxing it will throw an exception but using Convert.ToInt32, internally uses int.Parse.

Boxing and Unboxing (C# Programming Guide)

Attempting to unbox a reference to an incompatible value type causes an InvalidCastException.

Paraselene answered 6/10, 2016 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.