Why Does (Int)(Object)10M Throw "Specified Cast Is Not Valid" Exception

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);

Specified cast is not valid when I try to cast to (int?)

Indeed, DataTable doesn't support int? - you'd add it as an int - with DataTable handing nullability separately. For the cast, there are two possibilities:

  1. the value is DBNull
  2. the value is something else - not an int; perhaps a long or a string

For 1 - just check whether the value is DBNull, and if so: don't try casting it to an int - handle the null yourself.

For 2 - you'd have to do your own parsing / conversion code, but frankly: it would be better to fix the database so that it is right

However, frankly: I am going to say: tools like Dapper make this just go away - no DataTable, no worries. You'd just use things like a List<ProjectNeedsBolts> for POCO:

public class ProjectNeedsBolts {
public int Quantity {get;set;}

public int IdType {get;set;}
}

(or int?, or whatever else you need), then get the library to do all the work for you:

await conn.ExecuteNonQueryAsync(
"AddProjectNeedsBoltsTest",
new { Quantity, Filetage, IdProject, IdCategory, IdType }
commandType: CommandType.StoredProcedure).ConfigureAwait(false);

or:

var data = await conn.QueryAsync<ProjectNeedsBolts>(
"your select sql",
new {...} // parameters
}).ConfigureAwait(false);

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.

Why can't I unbox an int as a decimal?

You can only unbox a value type to its original type (and the nullable version of that type).

By the way, this is valid (just a shorthand for your two line version):

object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion

For the reason behind this read this Eric Lippert's blog entry: Representation and Identity

Personally, I categorize things done by cast syntax into four different types of operation (they all have different IL instructions):

  1. Boxing (box IL instruction) and unboxing (unbox IL instruction)
  2. Casting through the inhertiance hierarchy (like dynamic_cast<Type> in C++, uses castclass IL instruction to verify)
  3. Casting between primitive types (like static_cast<Type> in C++, there are plenty of IL instructions for different types of casts between primitive types)
  4. Calling user defined conversion operators (at the IL level they are just method calls to the appropriate op_XXX method).

Specified cast is not valid when using casting

Are any of the entries null for that field? or are there some that are not doubles?

we'd need to see more data to get a better answer...

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.

Specified cast is not valid (byte database, GetBytes)

student.Add(new Item()
{
ID = dr.GetInt32(dr.GetOrdinal("Id")),
itemImage = (byte)dr.GetInt32(dr.GetOrdinal("itemimage")),
itemName = dr.GetString(dr.GetOrdinal("itemname")),
itemDesc = dr.GetString(dr.GetOrdinal("itemdesc")),
itemQuantity = dr.GetInt32(dr.GetOrdinal("qituantity"))
});


Related Topics



Leave a reply



Submit