Casting Object to Int Throws Invalidcastexception in C#

Casting object to int throws InvalidCastException in C#

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.

Cast object containing int to float results in InvalidCastException

The problem you're running into here is that the C# cast operator means different things in different situations.

Take this example you gave:

object num = 10;
float fnum = (float)num;

The C# compiler will think you are telling it this: "The variable num refers to a boxed float; please unbox it and return the boxed value."

You're getting an error because it's not a boxed float, it's a boxed int.

The problem is that C# uses identical-looking syntax for two totally unrelated operations: 'unbox' and 'numeric conversion'. Here's an example of where a cast means numeric conversion:

int num = 10;
float fnum = (float)num;

Almost exactly the same code, and yet this won't give you an error. And that's because the C# compiler treats this completely differently - this code means: "Please perform a numeric conversion, converting the integer stored in 'num' into a single-precision floating point value."

How do you know which of these two utterly unrelated operations it's going to choose? It's all about the source and destination types. If you're converting from 'object' to a value type, that will always be treated as an unbox. If you're converting from one numeric type to another, that will always be treated as a numeric conversion.

So how do you get the result you want? Well, you need to do both operations: you need to unbox the int and then you need to convert it to a float. So you actually need two casts:

object num = 10;
float fnum = (float) (int)num;

Horrible huh?

The simplest way to do what you want here is to avoid casting entirely. Just do this:

float fnum = Convert.ToSingle(num); 

That will coerce the type to a single-precision float if it's possible to do so.

InvalidCastException while casting to OrganizationServiceContext

Although a CustomerCrmServiceContext is an OrganizationServiceContext, the opposite isn't true, which is why you're getting the exception.

A cast cannot magically change an object's type at runtime.

By using a cast, your essentially telling the compiler "Although you think this object is SomeBaseType, I know that, at runtime, it will always be an instance of SomeDerivedType so please treat it as such".

If it transpires that at runtime, the object isn't the type that you have tried to cast to, you will get an InvalidCastException, and an OrganizationServiceContext isn't a CustomerCrmServiceContext.

Explicit cast to defined type throws `InvalidCastException`

The reason the first code snippet works is that what you see is not a "straight" cast: it is an invocation of an explicit conversion operator. This operation is well-defined, and works exactly the way it is coded: a brand-new object B is constructed from A's value. C# has enough information to determine that the explicit operator is to be invoked, because new A(5) type matches the type of operator B(A value) parameter.

Once you add a cast to object, however, the compiler does a true cast. C# no longer has an applicable user-defined conversion operator, so it does the type check, determines that A is not convertible to B, and throws an exception.

There is a way to make it work without dynamic by building and compiling a dynamic lambda, like this:

private static B ConvertFromObject(object a) {
if (a == null) return null;
var p = Expression.Parameter(typeof(object));
var c1 = Expression.Convert(p, a.GetType());
var c2 = Expression.Convert(c1, typeof(B));
var e = (Func<object,B>)Expression.Lambda(c2, p).Compile();
return e(a);
}

Demo.

You could cache compiled lambdas by a's runtime type to save on the costs of compiling a new expression each time you run the method.

Why does (int)(object)10m throw Specified cast is not valid exception?

A boxed value can only be unboxed to a variable of the exact same type. This seemingly odd restriction is a very important speed optimization that made .NET 1.x feasible before generics were available. You can read more about it in this answer.

You don't want to jump through the multiple cast hoop, simple value types implement the IConvertible interface. Which you invoke by using the Convert class:

        object o = 12m;
int ix = Convert.ToInt32(o);

invalid cast exception on int to double

C# allows a conversion from int directly to double, but not from int to object to double.

int i = 1;
object o = i;
double d1 = (double)i; // okay
double d2 = (double)o; // error

The Enumerable.Cast extension method behaves like the latter. It does not convert values to a different type, it asserts that values are already of the expected type and throws an exception if they aren't.

You could try (new int[]{1,2,3,4,5}).Select(i => (double)i) instead to get the value-converting behaviour.

Convert.ChangeType throwing Invalid Cast Exception for nullable int

I'm assuming Claim.Value is of type Object and you're dynamically converting here, you can't straight up convert an int to an int? via Convert.ChangeType.

One option is to use Nullable.GetUnderlyingType which will check if this is a nullable struct case, do the conversion via the underlying data type first, then cast to T.

You'll also need to handle the null scenario as well.

if (claim != null)
{
var conversionType = typeof(T);

if (Nullable.GetUnderlyingType(conversionType) != null)
{
if (claim.Value == null) //check the null case!
return default(T);

//use conversion to `int` instead if `int?`
conversionType = Nullable.GetUnderlyingType(conversionType);
}

return (T)Convert.ChangeType(claim.Value, conversionType);
}

Puzzling Enumerable.Cast InvalidCastException

That's very odd! There's a blog post here that describes how the behaviour of Cast<T>() was changed between .NET 3.5 and .NET 3.5 SP1, but it still doesn't explain the InvalidCastException, which you even get if you rewrite your code thus:

var list = new[] { 1 };
var castedList = from long l in list select l;
Console.WriteLine(castedList.First());

Obviously you can work around it by doing the cast yourself

var castedList = list.Select(i => (long)i);

This works, but it doesn't explain the error in the first place. I tried casting the list to short and float and those threw the same exception.

Edit

That blog post does explain why it doesn't work!

Cast<T>() is an extension method on IEnumerable rather than IEnumerable<T>. That means that by the time each value gets to the point where it's being cast, it has already been boxed back into a System.Object. In essence it's trying to do this:

int i = 1;
object o = i;
long l = (long)o;

This code throws the InvalidCastException you're getting. If you try to cast an int directly to a long you're fine, but casting a boxed int back to a long doesn't work.

Certainly an oddity!



Related Topics



Leave a reply



Submit