Почему ReSharper не предлагает использовать нулевое распространение для обоих этих блоков? - PullRequest
0 голосов
/ 21 октября 2019

ReSharper предлагает использовать нулевое распространение для «повреждаемого» блока if, но для «forceVelocityCalculator» предложение отсутствует.

void Damage(Collider hitCollider)
{
    IDamageable damageable = hitCollider.GetComponent<IDamageable>();

    if (damageable != null)
    {
        damageable.TakeDamage(_damage);
    }
}

void Push(Collider hitCollider)
{
    ForceVelocityCalculator forceVelocityCalculator = hitCollider.GetComponent<ForceVelocityCalculator>();

    if (forceVelocityCalculator != null)
    {
        forceVelocityCalculator.Push(_pushForce, GameAPI.playerTransform.transform.forward);
    }
}

Я что-то упустил? Я бы использовал нулевое распространение для обоих блоков.

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Вероятно, из-за того, как Unity определила, что возвращается из GetComponent()

Если вы действительно действительно посмотрите на то, что делает GetComponent, то на самом деле никогда не вернет null, вы всегда получаете объектную оболочку, которая обрабатывает связь между вашим кодом C # и базовым кодом C ++ Unity.

Таким образом, когда вы получаете «null» из GetComponent(), то, что вы фактически получаете (Unity переопределяет оператор == !), На самом деле не равно NULL, а обертка объекта вокруг а null. Так что ReSharper не знает, что здесь может быть полезно распространение нуля (при условии, конечно, что оно работает: поскольку объект не на самом деле ноль, просто притворяясь нулевым, синтаксический сахар может не работатьправильно!).

0 голосов
/ 21 октября 2019

Использование нулевого распространения для объектов единиц (от которых унаследованы ваши компоненты неверно ), поэтому Resharper не предлагает этого делать, но Visual Studio 2019 фактически выдает предупреждение об этом.

Почему он предлагает для IDamageable хотя? потому что это интерфейс, а IDE (редактор кода) не знает, какой тип объекта представляет этот экземпляр интерфейса до времени выполнения.

Так что он позволяет это (или не предупреждает об этом, но во время выполнения его распространение выиграло ')не работает должным образом), потому что интерфейсы не наследуются от UnityEngine.Object, очевидно, но ForceVelocityCalculator наследуется от MonoBehaviour или ScriptableObject, у которых UnityEngine.Object в качестве конечного родителя, который отменяет проверку нуля, что означает распространение нуляязык C # - это не то же самое, что проверка нуля для объектов единиц, потому что единица отменяет проверку нуля.

Unity делает что-то особенное с оператором ==. Вместо того, что большинство людей ожидают (на языке C # для не UnityEngine.Object объектов), Unity имеет специальную реализацию оператора ==.

Это служит двум целям:

  1. Когда у MonoBehaviour есть поля, только в редакторе Unity устанавливает для этих полей значение «реальный ноль», а не объект «фальшивый ноль». и пользовательский оператор == может проверить, является ли что-то одним из этих поддельных нулевых объектов, и ведет себя соответственно.

    • Хотя это экзотическая установка, она позволяет единице хранить информацию в поддельном нулевом объекте, который дает вам больше контекстной информации, когда вы вызываете метод для него или когда вы запрашиваете у объекта свойство,
    • Без этого трюка вы бы получили только NullReferenceException, трассировку стека, но вы не знали бы, что у GameObject было MonoBehaviour с полем, равным нулю. С помощью этого трюка Unity может выделить GameObject в инспекторе, а также может дать вам больше указаний: «похоже, что вы получаете доступ к неинициализированному полю в этом MonoBehaviour здесь, используйте инспектор, чтобы заставить поле указывать начто-то ».
  2. Когда вы получаете объект ac # типа GameObject, он почти ничего не содержит. это потому, что Unity - это движок C / C ++. Вся фактическая информация об этом GameObject (его название, список компонентов, его HideFlags и т. Д.) Находится на стороне c ++. Единственное, что имеет объект c # - это указатель на нативный объект.

    • Вы можете называть эти объекты c # «объектами-обертками». Время жизни этих объектов c ++, таких как GameObject и все остальное, что происходит от UnityEngine.Object, явно управляется. Эти объекты разрушаются при загрузке новой сцены. Или когда вы звоните Object.Destroy(myObject); на них.
    • Время жизни объектов c # управляется способом c # с помощью сборщика мусора . Это означает, что возможно иметь объект обертки ac #, который все еще существует, который обертывает объект c ++, который уже был уничтожен. Если вы сравните этот объект со значением NULL, пользовательский оператор Unity == в этом случае вернет «true», хотя фактическая переменная c # на самом деле не является нулевой, , но нулевое распространение , скажет, что UnityEngine.Object все еще существует, когда его магистрали нет, это просто фасад, который все еще жив, надеюсь, это имеет смысл.

Источник

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...