Cast object containing int to float results in InvalidCastException
Asked Answered
I

4

7
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    var fP18VaR = (float) (int)e.Values[0];
}

I'm getting

InvalidCastException - Specified cast is not valid

Why doesn't it work?

The value of e.Values[0] is: 6 666,00

Institutionalize answered 27/6, 2014 at 8:33 Comment(9)
What is e.Values[0], a Horse? Edit So it is 6 666,00, the decimal/double number or a string?Clactonian
Maybe the cast to int already fails?Mauretania
e.Values[0].GetType()?Riding
I agree to @UweKeim .. I think that the values are related to some other data type.Chishima
is this really a 6[whitespace]666,00 ? If so, the int parse probably already failsMalvasia
@Serv there is no int parsing, just castingHarvester
Hmm ok..How can I work around this?Institutionalize
First of all, you need to explain what you are trying to do. Describe exactly how you wish to convert "6 666,00" into an integer and then a float.Rittenhouse
Other questions/duplicates all combining to a full answer: Why does (int)(object)10m throw “Specified cast is not valid” exception?, Why can't I unbox an int as a decimal?, Casting object to int throws InvalidCastException in C#Couchant
P
29

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.

Pedicle answered 27/6, 2014 at 8:39 Comment(0)
R
2

The compile time type of e.Values[0] is Object. So, you do need to cast and or convert to obtain a float. If

(int)e.Values[0]

succeeds, then

(float) (int)e.Values[0]

will succeed. Ergo, e.Values[0] cannot be converted to an int.

Your next step is to work out what the runtime type and value of e.Values[0] is, and try to understand how to convert that to a numeric value.

Rittenhouse answered 27/6, 2014 at 8:37 Comment(0)
R
1

Your cast is not valid because e.Values[0] return boxed value as object, which first need to be cast to correct underlying type. To cast underlying value to float, you need to specify correct type first.

Also, if object is not a value type, but some other container, or for example, string - you need to cast to this container first, and then find a way how to convert this to float.

Eric Lipper has excellent article on this subject: Representation and Identity.

Radie answered 27/6, 2014 at 8:38 Comment(0)
F
1

Consider using TryParse instead; slightly verbose example below to give you an idea how to handle errors parsing and how to subsequently convert the nullable float to a regular one:

protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    float? temp;
    if (!float.TryParse(e.Values[0], out temp))
    {
        //code to handle problems parsing here
        throw new InvalidCastException("Invalid cast: '{0}' cannot be parsed to a float", e.Values[0]);
    }
    //if we reach here (we've not thrown an error above), `temp` is not null
    var fP18VaR = temp.Value;
}

NB: this function takes the current culture into account; so if you're working with multi-cultural data you'll need to be aware of what format the numbers are in. See http://msdn.microsoft.com/en-us/library/3s27fasw(v=vs.110).aspx for more info.

Fredra answered 27/6, 2014 at 8:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.