Search Unity

Feedback Is it possible to move TryGetComponent into extension method?

Discussion in 'Scripting' started by Thaina, Jun 28, 2022.

  1. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,161
    Actually all functionality of GameObject related to GetComponent itself should be moved into extension method so that it would check for null and return null instead of throwing exception

    Code (CSharp):
    1.  
    2. class GameObjectExt
    3. {
    4.     public T GetComponent<T>(this GameObject obj)
    5.     {
    6.         if(obj == null)
    7.             return null;
    8.         return obj.InternalGetcomponent<T>();
    9.     }
    10.  
    11.     public bool TryGetComponent<T>(this GameObject obj,out T component)
    12.     {
    13.         if(obj == null)
    14.             return false;
    15.         return obj.InternalTryGetcomponent(out component);
    16.     }
    17. }
    18.  
    19. ////////////////////////////////////////////////////////////////
    20.  
    21. var myComponent = GameObject.FindGameObjectWithTag("Player").GetComponent<MyComponent>(); // Not throw exception if null
    22.  
    23. if(GameObject.FindGameObjectWithTag("Player").TryGetComponent(out MyComponent component)) // Not throw exception if null
    24. {
    25. }
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,818
    Um, why? It's just syntax sugar. It wouldn't make any difference.
     
  3. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,161
    Do you know `NullReferenceException` ?
     
  4. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,647
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,818
    Yeah this has nothing to do with it being an extension method or not.

    GetComponent/TryGetComponent don't throw an exceptions if it doesn't find the component, it just returns null. You only get an exception if you try and do anything with the null reference, which is just a standard C# thing at that point.

    TryGetComponent exists to allow us to check for components in a more elegant manner.

    If you're expecting the component and don't get it, you're doing something wrong. That's for you to debug.

    This is a pretty fundamental facet of Unity and C# that I would hope someone that has an account from 2012 would understand.
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,979
    While it would be possible for Unity to move those methods into an extension method where they could catch issues where the object itself is null, such behaviour would be misleading and would not be expected. That would mean when the method returns null it could mean several different things at once which makes debugging much harder. You are free to create such an extension method yourself and give it a descriptive name. Since you named your extensions just GetComponent and TryGetComponent (which of course is not possible at the moment) it shows you haven't come up with a good descriptive name. Every C# programmer expects to get a null reference exception when you try dereference a reference. This happens when you try to access any instance member of a reference type. Extension methods are an expection to this rule and just implementing something as extension method to hide an error is just bad code.

    Of course C# has now the
    ?.
    operator which you may have in mind here, which unfortunately doesn't work with fake null objects. Though the important part is, using the null conditional operator is an explicit choice by the programmer and the intent is clear by reading the code. Hiding null checks inside extention methods would not be obvious. Extension methods are just a way to add functionality to a class / type that you can't modify yourself. Extension methods are meant to make the code cleaner and more expressive and should not hide magic that goes against the normal programming rules.

    So if you implement a method like this, you should come up with a descriptive name that makes it clear what it does. For example I once created an extension method called
    GetOrAddComponent<T>()
    . I'm pretty sure you can infer what this method does. However I don't do a null check inside that method because executing this method on a null reference is an error. So come up with a better / more descriptive name for your extension method, implement it and use it instead.
     
    passerbycmc and PraetorBlue like this.
  7. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,908
    There's nothing stopping you from making your own extension method that does this.
     
  8. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,161
    This means you just don't understand

    Look at the code sample in the thread. And think again. How many places can be null from that line of code

    Being extension method can be call even if the caller object is null. That is the magic of extension method. Because it is actually static function in disguise. You can really use null gameobject to call extension method, try it and see if I am wrong

    I am always include these extension method along with many of my utility extension method I have into every of my project and I think this should be standardize so everyone should use it instead of `get object > check null > get component` which is tedious and annoying

    `GetOrAddComponent` also one of those. It should be officially made into unity standard extension method so people will not bring thier own into project just to collide with each other
     
  9. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,818
    Okay, I misunderstood you, apologies, though admittedly your initial explanation was rather brief and lacking detail.

    Disagree. The current behaviour is expected and should be throwing exceptions when the game object is null. Not throwing exceptions when the game object is null doesn't really solve anything aside from 'convenience'.
     
  10. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,161
    I am not against making a new name or anything if it should be, I just want it to be an officially standard from unity so that everyone will use it with the same manner
     
  11. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,161
    convenience is the reason why we have computer language. Arguably every language feature is just syntactic sugar because you can write everything in binary machine code
     
  12. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,818
    Beside the point. Convenience is completely irrespective of expected behaviour.

    What you're suggesting completely changes the behaviour of one of the most core aspects of Unity's API. Never going to happen.
     
  13. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,908
    On the contrary, I'd argue adding unnecessary null checks is at best an unnecessary performance hit, and at worst it makes debugging a whole lot more confusing. If my GetComponent returns null I'm expecting that to mean that there is no such component on that GameObject, not that my reference itself is null.
     
    Last edited: Jun 28, 2022
    spiney199, Bunny83 and passerbycmc like this.
  14. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    Having methods magically work on null references instead of throwing exceptions is not a good practice, it just pushes the bug (having a bull reference where there shouldn't be one) forward.
     
  15. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,161
    On that note the fake null of unity also not a good practice but we use it anyway. Unity is not good practice around this regard. If unity stop using the fake null we then would use `??` and `?.` like normal C#
     
  16. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    No, even removing the fake null you wouldn't be able to use ?? and ? safely, because you'd still need some way to check if the underlying C++ object is still valid, the same way you would, for example, using an IDisposable which was already disposed.
     
  17. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    if something is null that i was not expecting to be null and am not checking for, i want it to blow up and throw a exception i do not want to just kick the problem further down the callstack. Also if i have a game object and intend to do nothing else but GetComponent it i would be question why i am not referencing that component directly as well.

    This would just make debugging of code worse. Also if you really wanted it, you could easily add your own extension methods it does not have to be part of Unity. Hell could even do your own package manager package for it.
     
    Last edited: Jun 28, 2022
    Bunny83 likes this.
  18. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    That would not be the case though, like you would still need to check for .IsAlive or where ever else they put the check for the status of the native side of your UnityEngine.Object if it was not done through the equality override. If you really wanted to use the ?. and ?? syntax you could easily do that via extension methods as well.
     
    Bunny83 likes this.