- Home /
Try-catch alternative
Hi!
I made a script to constantly change the color of a Sprite. Then I decided to also constantly change the color of a Panel on my GUI.
So, in the one case there is a SpriteRenderer, in the seccond case there is an Image instead.
My thoughts: I try to assign a SpriteRenderer to a variable, if I can't do that it means the script is running inside a Panel, then I get an Image.
I changed the code to work on both, a Sprite and a Panel.
I tried this:
try {
spriteRenderer = GetComponent<SpriteRenderer> ();
isSprite = true;
}
catch{
isSprite = false;
img = GetComponent<Image>();
}
For no effect. Actually, it showed me a message error telling me my Panel has no SpriteRenderer.
Then I tried this:
if(spriteRenderer = GetComponent<SpriteRenderer> ()){
isSprite = true;
} else {
isSprite = false;
img = GetComponent<Image>();
}
Which works exactly like I expected the try-catch would.
My question: WHY?
Isn't the try-catch supposed to be used in cases like this?
a bad use-case in you situation would be:
try{
GetComponent<SpriteRenderer>().enabled = true;
}catch(Exception){
Debug.Log("No renderer was found");
}
See I am accessing a member without checking that the method returns anything. But to be honest, try/catch should be used only if it should since it is slow.
if(spriteRenderer = GetComponent<SpriteRenderer> ()){
this line is fine and better since the method returns the component or null, then place it in the spriteRenderer reference and the if statement checks if this one is null or not. Better wording (personal) would be:
SpriteRenderer sp = GetComponent<SpriteRenderer> ();
if(sp != null){
// Action on sp
}
It is not slower and it is clear what I am doing.
A legit use of try/catch would be for instance when parsing a json file. You are expecting a float, but some careless trainee (who got fired after that) put something wrong on the server and when you try to convert to float, it crashes:
try{
JSONFile json = JSON.GetJson(file);
string str = json.GetString("floatValue");
float value = float.Parse(str);
}catch(Exception e){
Debug.Log(e.$$anonymous$$essage);
}
In this case, it makes sense (though you can use ParseFloat ins$$anonymous$$d to avoid the exception).
Answer by steakpinball · Aug 20, 2015 at 02:24 PM
try / catch
is to catch exceptions thrown by methods. It doesn't work here because GetComponent
doesn't throw any. Instead when a component is not found it returns null
. Putting a component variable in an if
statement checks whether the variable exists (is non-null).
If you want to use exceptions you can use an intermediary method.
T GetComponentWithException<T>() where T : Component
{
var c = GetComponent<T>();
if (c)
return c;
throw new ArgumentException(typeof(T).Name + " could not be found.");
}
I see...I should look the documentation more carefully.
Thanks for the answer, it was very helpful.
Answer by ninjapretzel · Aug 21, 2015 at 05:58 PM
The line:
if(spriteRenderer = GetComponent<SpriteRenderer> ()){
is an assignment statement '=', not an equality check '=='. However, C# will check the result of the assignment if it can be converted to a boolean, which UnityObject can be. If they couldn't become a bool value, then the code would not compile. UnityObjects can't actually be null, they have a special value that is returned in place of null for any 'null' reference to a UnityObject returned by one of Unity's built-in functions like GetComponent.
The code you have works because the fake 'null' UnityObject converts to 'false', and any real UnityObject converts to true.
As an aside, you might want to get more familiar with the C# language to understand these kinds of werid things. Unity does some werid things, and I remember a blogpost about this werid behaviour with nulls and bools a few months back.
Your answer
Follow this Question
Related Questions
Stop Game on Exception 4 Answers
Joystick.cs Invisible 1 Answer
try{}catch{} not catching Mesh.vertices is too small. 0 Answers
Try catch alternative for HTTP request 1 Answer
Can you use yield and Try/catch in the same function? 1 Answer