- Home /
Make compiler treat an object variable as if it was of type X
Hey everyone, I've got a problem here that already had me trying for hours: I have an input which is an object variable (For certain environmental reasons it really cannot be anything but an object), but in reality it's of the type FsmPath .
Now I need to access some public attributes which do not exist in the object variable. Eg, my input is "OutputPath"
(...) [ObjectType(typeof(FsmPathfinding.FsmPath))]
public object OutputPath; (...)FsmPath doo = (FsmPath)OutputPath;
This is the only way I found to cast it from an object to a FsmPath. If I do not do this it gives me errors if I try to access attributes. However, if I do it like this it also gives me errors, because it has to convert the variable from source to destination type. Logically this would not be a problem. I could just do :
FsmPath doo = OutputPath.GetType() == typeof(FsmPath) ? OutputPath : (FsmPath)OutputPath;
In my thoughts this would set doo to the FsmPath variable if it was already of that type, and it would cast it to that type even if it wasn't. Sadly the compiler still disagrees.
What can I do to solve this? How can I make it obvious to the compiler that the object variable is never something other than a FsmPath variable, without actually making the input one?
I don't really know, but have you tried something like (yourVariable as FsmPath). Or maybe thats the same as (FsmPath)yourVariable in C#?
it's not quite the same, but it did not work either. Thanks for the input though :)
Answer by Bunny83 · Jan 18, 2013 at 08:34 PM
Your points don't make any sense to me. I don't see any reason why you have to use a variable of type object when it's always a FsmPath. The only reason would be because it's not always a FsmPath. In this case the compiler doesn't know the type at compile time, so you have to cast it to your desired type. A cast only works when the object stored in the object variable is a FsmPath. If it's not a FsmPath you can't turn it into a FsmPath.
This line:
FsmPath doo = OutputPath.GetType() == typeof(FsmPath) ? OutputPath : (FsmPath)OutputPath;
also makes no sense at all. You use reflection to test if the stored object is of type FsmPath and if it is you just assign the object variable to the FsmPath variable which doesn't work without a cast. Even worse is your alternative case. If it's not a FsmPath you try to cast it to FsmPath which is impossible since the object is not a FsmPath.
The usual way to text for a specific type is the "is" operator:
if (OutputPath is FsmPath)
{
FsmPath fsmPath = (FsmPath)OutputPath;
// do something with the fsmPath
}
else
{
// It's not a FsmPath so either test for other possible types or do nothing.
}
ps: You have to distinguish between value-conversion-casts and type casting. A conversion cast will transform the source object into something different. That type of cast is mostly used for value types. (for example casting a float to an int).
Type casts however can't convert anything. It just tells the compiler that you "think" this object should be of the given type. When it's not the runtime will throw an exception.
I see I should have been more specific in my explanation, sorry. The FS$$anonymous$$ system I use (Play$$anonymous$$aker) has a number of variables per FS$$anonymous$$ which I can use in a lot of actions. The GUI has been designed in a way that I can create a float variable for example, and then plug it into a "get Distance" action (like a function) and it will then save the result to the variable. I can then plug that variable into another action as input for example. This variable system works on top of the normal action system, as each action is an individual script. Therefore each type of variable needs a specific GUI "socket" in the action scripts, so people can easily drop in their variables. The problem with this is that Play$$anonymous$$aker is not open source, only the actions are. So I can not extend the base classes and cannot add new GUI support. If I create a public FsmPath in an action, I can assign stuff to it only like I can in the normal unity gui(drag and drop or absolute pointer). This is why there's no other choice than using object variables, especially since paths are generated at runtime.
$$anonymous$$y code snippet was my try to create a scenario where no matter what, the result would always be of the type FsmPath. What I need is : FsmPath doo = OutputPath; since I already know that OutputPath is of the type FsmPath. But of course the compiler wants an explicit type cast. So then I'd go for FsmPath doo = (FsmPath)OutputPath; Great, works without errors, but when I call the script in runtime I get an error telling me I can't cast from source to destination type. $$anonymous$$y above snippet should logically have addressed both compiler issues, but apparently it doesn't recognize that.
So I had been hoping that there might be a way to tell the compiler to always cast unless casting itself would cause an error.
Did that make more sense?
Like i said, your first example is correct when you are sure that it is a FsmPath. Since you get a cast exception at runtime it clearly is not a FsmPath, so you have to decide what you do in this case because there's no way to turn it into a FsmPath when it's something different. You can not turn a potato into an apple even both are "food".
Btw, i never used Play$$anonymous$$aker myself, so i can't tell you if you're using it right ;) I know that you have casting problems but it's still not really clear what you want to do. If you want to know how Play$$anonymous$$akre works internally you can use $$anonymous$$onoDevelops Assembly browser to decompile the dll. however i prefer ILSpy which works way better
Answer by kat0r · Jan 18, 2013 at 06:26 PM
"(For certain environmental reasons it really cannot be anything but an object)" Are you really sure of that? Maybe you could overload your function with a version that accepts FsmPath instead of Object.
I'm writing this as an indepth integration of aaron's pathfinding into hutong games' Play$$anonymous$$aker FS$$anonymous$$ system. Playmaker only supports custom types by saving them in object variables. Since there is no open source I can't implement my new variables directly. All I can do is make sure that only object variables containing a certain type can be used as input(as you can see in the very first line of code above).
I think one possibility would be instantiating the object variable, at least that's what I've read so far, but that also wouldn't do since I want to save the real thing.