I get the following error when trying to convert an object to float:
System.InvalidCastException: The cast specified is invalid.
menu[i].weight = (float)dataGridView1[j, i].Value;
CodePudding user response:
You can use float.TryParse
and pass object convert ToString()
as parameter. Please see below.
object obj = 2.111;
float height;
if (float.TryParse(obj.ToString(), out height))
{
//success
Console.WriteLine(height);
}
else
{
//failed
}
CodePudding user response:
The value you're converting, as others have stated in the comments, is not truly a float
- but that might be confusing, because it might look like a float
- here's an example of a possible scenario:
object maybeFloat = 1.25; // looks like a float, but is actually a double!
float wontWork = (float)maybeFloat;
The above cast will fail, throwing an InvalidCastException
- because the actual item stored (technically known in C# as boxed, in the case of struct
s, such as int
, float
, double
, as well as custom struct
types) is a double
, not a float
. There are several "fixes":
- Store a float:
object someFloat = 1.25f; // Notice the `f` after the number - that's a float!
float willWork = (float)someFloat;
... but that's not always possible - the data might be coming from some external source, such as a database, etc. In that case, float.Parse
to the rescue:
object maybeFloat = 1.25; // Still not a float... but can be parsed as one!
float willWork = float.Parse(maybeFloat.ToString()); // float.Parse requires a string,
// hence the `.ToString()` call
This will work if the object contains a value that is in fact parseable into a float
datatype. So, the above example works for parsing a boxed double
into a float
(notice, some data loss may occur - not in the above example, but in general, because float
is a smaller data type than double
). This will also work if the value stored is a string
(as an aside, string
s are not boxed, because they are reference types). Perhaps strangely, the .ToString()
call is still required - because there is no implicit conversion from object
to string
:
object maybeFloat = "1.25"; // Still not a float... but can be parsed as one!
float willWork = float.Parse(maybeFloat.ToString()); // no implicit conversion,
// hence the `.ToString()` call
... but what if the value stored is really, really, not a float at all? Well, then float.Parse
will fail, most likely throwing a FormatException
, indicating that the supplied value is really not parseable into a float
datatype. You can catch the exception with a try/catch
block:
object maybeFloat = "one point two five"; // hmmm... that won't parse into a float!
float result = default;
try
{
result = float.Parse(maybeFloat.ToString());
}
catch (FormatException _)
{
// Handle error here!
}
...however, there's a better way - float.TryParse
:
object maybeFloat = "one point two five"; // will fail to parse!
bool isSuccessfullyParsed = float.TryParse(maybeFloat.ToString(), out var result);
if (!isSuccessfullyParsed)
{
// Handle error
}
else
{
// `result` will contain the properly parsed float value
}
Ok, this should give you a pretty good idea of what's happening in your specific case. Final note, the .Parse
and .TryParse
methods exist on all .NET numeric types - int
, long
, float
, double
, decimal
, even BigInteger
- so same technique applies to all of them.