Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Mono Upgrade Using the null-conditional operator with components using .NET 4.x

Discussion in 'Experimental Scripting Previews' started by Destrucity, Jul 23, 2018.

  1. Destrucity

    Destrucity

    Joined:
    Sep 28, 2014
    Posts:
    17
    For example, with the code
    GetComponent<AudioSource()?.Play();
    I will get a missing component exception if there is no AudioSource on the game object.

    I would expect the ?. null-conditional operator to guard against this exception. Is this a bug or am I missing something?
     
    AntonioModer likes this.
  2. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    https://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/

    basically, 2 things happen:
    - UnityEngine.Object overloads the == operator, so that "== null" returns true if the object is missing or has been destroyed, but the variable does not contain a real null
    - in the editor, GetComponent<>() returns a "fake null" object if the component does not exists

    meanwhile, the "??" and "?." operators check for real null, bypassing the overload and basically doing a hard "ReferenceEquals".
    this results in the "?." check to pass (managed object is not null)
    finally, Unity throws MissingReferenceException from C++ when you call AudioSource.Play() on a null (according to Unity) object
     
    AntonioModer likes this.
  3. Destrucity

    Destrucity

    Joined:
    Sep 28, 2014
    Posts:
    17
    Thanks for clarifying! This explains why the behavior is happening. I guess my follow-up question is, should that be what happens? It would be nice to use the ?. operator without remembering esoteric special cases.
     
  4. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    the main problem is that an UnityEngine.Object can be destroyed, and there is no way to magically set all references to null every time you destroy something (the closest thing they could do is basically a full GC collect).

    you could create your extension method that does the manual check and returns a real null when you access the object, then you could do
    GetComponent<AudioSource>().SanityCheck()?.Play()
    . (protip: extension methods can have a null
    this
    because they are actually static methods with syntax sugar)
     
    AntonioModer likes this.