- Home /
The question is answered, right answer was accepted
Is There A Way To Cast On 1 Returning Value 2 Times?
I Decided To Test My Script On Integers And It Gives Me An Error:
Cannot cast from source type to destination type.
And I Know What It Means And How To Solve It, However In My Script The Returning Value Is Unknown If It's Int Or Float! And I Want It To Work For Both Float And Int! So I Want To Do Something Like This:
value = (float)(int)source.GetType().GetField(valueName).GetValue(source);
Originally It's Like This Now:
value = (float)source.GetType().GetField(valueName).GetValue(source);
The (value) Is A Float, And The Returning Value Might Be An Int, So It Throws Errors! Is There A Way To Cast On The Returning Value 2 Times? If I Change It To (Int), Then If The Returning Value Is A Float, It Gives Me The Same Error!
Thanks..
Answer by $$anonymous$$ · Aug 07, 2017 at 01:56 PM
Thanks For Everyone's Answers, But Most Of Them Didn't Work, I Got It To Work Like This In 1 Line! :
value = float.Parse(source.GetType().GetField(valueName).GetValue(source).ToString());
Thanks :D
Until your source cannot be parsed to a float, and then you have an error.
No It Works Fine For Both Returning Float And Int Values, Seems Like Parsing Float To Float Works :D
It's bad practice. Consider something else if you can.
That's whats commonly known in program$$anonymous$$g circles as a train wreck statement.
You are implying that each method in that chain will return something. If it doesn't then the whole statement will crash.
Split up your method returns into variables and check them for values before moving to the next method.
Glad you got it working though. I've updated my answer. Give it a try.
Don't bother, some people just want to watch the world burn. :P
What Are You 2 Talking About?? Is float.Parse(string) A Bad Way To Do This?
Are you sure you read my answer, at all? Because it's the right way. Converting a number into a string just to parse it back into a number is just unnecessary overhead.
I Had Read Your Answer, Tried It, And Gives $$anonymous$$e This Error:
The name `Convert' does not exist in the current context
Thats because you are missing a using System;
Turn this
value = float.Parse(source.GetType().GetField(valueName).GetValue(source).ToString());
Into this:
var sourceType = source.GetType();
var sourceField = sourceType.GetField(valueName);
if (sourceField == null) return null;
var sourceValue = sourceField.GetValue(source);
if (sourceValue == null) return null;
var value = (float)sourceValue;
But even this is stupid. You are implying that you know that the sourceValue is a float. In which case it should be a float at the point of declaration.
With my code you would just have to do this:
var value = GetValue<float>(source, valueName);
It Looks Long For $$anonymous$$e, $$anonymous$$y Point Is To Achieve The Same Thing As The JavaScript One, This C# Script Is A Copy And Converted Script From A JavaScript Code! $$anonymous$$y Primary Scripting Language Is JS! Which I Don't Like Having Long Lines For Something That Is Small :)
Answer by cgarossi · Aug 07, 2017 at 01:46 PM
You can get the type you want by just delving a little deeper into reflection.
You should create a generic method where you pass in the type you want and the method works it out for you. However, you really should know the type in advance because otherwise subsequent code cannot be written safely to deal with it.
public T GetValue<T>(object valueObject, string fieldName)
{
var valueObjectType = valueObject.GetType();
var valueObjectField = valueObjectType.GetField(fieldName);
if (valueObjectField != null)
{
var value = valueObjectField.GetValue(valueObject);
if (value.GetType() == typeof(T)) return (T)value;
}
throw new InvalidCastException("value is not of expected type T");
}
This will accept a Type (T) and return a value of Type T if it can read the value into that given type.
For example:
var value = GetValue<float>(myObject, fieldName);
This will return a float because you've asked for one in the . This is better than just trying to cast to every different type.
I Like The $$anonymous$$ethod You Provided But It's Too Long For Just Casting Float And Int On 1 Value :D
It's never too long if you want to be certain something won't break.
Sorry shady, I keep replying to the wrong comment :D
It doesn't just do floats though. It can do any type.
Put the code in a static tools class and you can use it whenever.
This method is pretty pointless. It does literally the same as the original line:
value = (float)source.GetType().GetField(valueName).GetValue(source);
There's no difference. If the field type is float it will work. If it's something else it will throw an exception.
So this answer doesn't address the actual problem at all.
There isn't actually a problem though. If you don't know the type at design time you $$anonymous$$UST test for it. So you must make a best effort attempt at finding the value by hinting at the type.
The above method allows you to check for any type and return it's value. But whatever the case you have to provide a type, whether it's via a cast or a generic method such as above.
Answer by ShadyProductions · Aug 07, 2017 at 01:27 PM
public float CastToFloatOrInt(string value)
{
// Try float first
float data;
if (float.TryParse(value, out data))
{
return data;
}
// Try int next if float doesn't work
int data2;
if (int.TryParse(value, out data2))
{
return data2;
}
// If not float or int can be cast throw exception
throw new System.Exception("Error cannot cast " + value + " to float or int");
}
Try something like this. Will always return a float, but it will be able to cast ints to float too.
You might have to cast to string first before you pass it to the method.
source.GetType().GetField(valueName).GetValue(source).ToString();
This line:
(string)source.GetType().GetField(valueName).GetValue(source);
won't work as the actual type is a boxed value type which can't be converted to string. However you can simply call ToString on the resulting object. Every object has a ToString method, even boxed number types.
Won't that simply return the object type name?
No. When you do for example:
string s = "hello " + 5;
The compiler automatically uses ToString. So the line actually reads as:
string s = "hello " + 5.ToString();
ToString of classes by default return the classname because there's no meaningful way to turn an arbitrary class or struct type into a string. However every class or struct can override the ToString method (which is virtual) and implement your own representation.
For example Unity's Vector3 struct overrides the ToString method to actually print the values of the 3 components.
All primitive types do have a custom ToString implementation. This includes all number types but also enum types and bool
Thanks But It Gives $$anonymous$$e This Error:
SharedObjects.Utility.CastFloatAndInt(string)': not all code paths return a value
That's not possible. Have you removed the throw new System.Exception
at the end? If you don't want to throw an exception you have to return some sort of default value at the end ins$$anonymous$$d. Something like:
return 0;
Answer by Bunny83 · Aug 07, 2017 at 01:32 PM
Not with a cast, no. There are three seperate things that can be performed with a cast:
A plain type cast, only relevant for reference types
Unboxing a boxed primitive type
An explicit type conversion
In your case you want to perform the last two things at the same time which doesn't work since they do two seperate thing. Unboxing a boxed primitive type only works when you specify the actual type. Once unboxed it can be converted. This is what (float)(int)
does. You unbox a boxed integer value and then convert it to float.
The most common alternative when using reflection is to use Convert.ChangeType. It's able to do a type conversion on a boxed value type. This way you can always convert the value into float and then unbox the float
object o = source.GetType().GetField(valueName).GetValue(source);
float value = (float)Convert.ChangeType(o, typeof(float));
This should work with any type that can be explicitly converted into float (byte, short, int, long, double, ...).
Answer by tsnyder321 · Aug 07, 2017 at 01:37 PM
@Limbornado ,
So if I am understanding this correctly, you are trying to take a value that you are uncertain as to its type (int or float) and trying to store it, correct? If so, you may want to make use of the C# implicit type var.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var
So using the example you gave, use:
var value = source.GetType().GetField(valueName).GetValue(source);
Then you should be able to use value.GetType() to find out its type and then cast accordingly.
var will give the returning type, which is object on GetValue. Not very useful.
The following code is what I used to test before posting the answer here, and it works fine.
int myTest = 1;
float myTestTwo = 2;
var implicityType = myTestTwo;
if(implicityType.GetType() == typeof(int))
{
Debug.Log("Is int");
}
else if (implicityType.GetType() == typeof(float))
{
Debug.Log("Is float");
}
Depending on if the var is set to the int or float, it will enter the correct code block based on type. So unless I am missing something (which is quite possible) it should work.
Yes you are checking the underlying type, which is fine. But the object returned is object.
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Error when checking if float is a whole number 2 Answers
C# Int to Float conversion performance 3 Answers