为什么ReSharper不建议对这两个块都使用空传播? [英] Why does ReSharper not suggest using null propagation for both of these blocks?

查看:74
本文介绍了为什么ReSharper不建议对这两个块都使用空传播?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ReSharper建议对可损坏"容器使用空传播.if块,但对于"forceVelocityCalculator"而言,一个没有建议.

 无效损坏(对撞机hitCollider){var Damageable = hitCollider.GetComponent< IDamageable>();如果(可损坏!= null){TakeDamage(_damage);}}无效Push(Collider hitCollider){var forceVelocityCalculator = hitCollider.GetComponent< ForceVelocityCalculator>();如果(forceVelocityCalculator!= null){forceVelocityCalculator.Push(_pushForce,GameAPI.playerTransform.transform.forward);}} 

我错过了什么吗?我将对两个块都使用空传播.

解决方案

Unity提供了 GameObject .

  • 由于Unity是C/C ++引擎,并且您使用C#编写脚本,因此您可以想到C#对象可以包装" C ++对象.有关该GameObject的所有信息(附加的组件,HideFlags等)都在C ++对象中.同样,这些C ++对象的生存期也得到明确管理.这就是为什么您使用 Object.Destroy()而不是将其设置为null的原因.定制的 == 运算符解决了C ++对象已被破坏但包装" C#对象仍然存在的情况.在这种情况下,即使您的C#对象在技术上不为null, CSharpObject == null 也会返回true.

  • ReSharper suggests using null propagation for the "damageable" if block, but for the "forceVelocityCalculator" one there is no suggestion.

    void Damage(Collider hitCollider)
    {
        var damageable = hitCollider.GetComponent<IDamageable>();
    
        if (damageable != null)
        {
            damageable.TakeDamage(_damage);
        }
    }
    
    void Push(Collider hitCollider)
    {
        var forceVelocityCalculator = hitCollider.GetComponent<ForceVelocityCalculator>();
    
        if (forceVelocityCalculator != null)
        {
            forceVelocityCalculator.Push(_pushForce, GameAPI.playerTransform.transform.forward);
        }
    }
    

    Am I missing something? I would use null propagation for both blocks.

    解决方案

    Unity offers a blog post about this topic, but a short summary follows.

    Null propagation on Unity objects, which your components inherit from, is incorrect. Resharper doesn't suggest doing it and Visual Studio 2019 gives a warning about it.

    Why does the suggestion occur for IDamageable? Because it's an interface. The IDE(code editor) doesn't know the type for an instance of this interface. It can't know that IDamageable inherits from UnityEngine.Object, so no suggestion occurs. ForceVelocityCalculator, however, inherits from MonoBehaviour or ScriptableObject, both of which inherit from UnityEngine.Object. This is significant because Unity has customized the == operator. In this way, the default equality comparison you're used to is not what happens.

    The blog post gives two reasons for this decision:

    1. Within the Editor, Unity has its own concept of null. Uninitialized fields of a MonoBehaviour are given this Unity-specific null value. This, combined with a custom == operator, lets Unity provide additional information to you, the developer, while you develop. Instead of receiving a NullReferenceException and standard stack trace, you instead receive an enhanced stack trace plus some indication of which GameObject the problem exists for. The blog posts mentions a neat feature where they highlight the problematic GameObject within the Hierarchy pane.

    2. Since Unity is a C/C++ engine and you write scripts in C#, you can think of your C# objects "wrapping" the C++ objects. All of the information about that GameObject (attached components, HideFlags, etc) are in the C++ object. Also, the lifetime of these C++ objects is explicitly managed. It is why you use Object.Destroy() instead of setting things to null. The custom == operator solves the scenario where a C++ object has been destroyed but the "wrapping" C# object still lives. In this case, CSharpObject == null returns true, even though your C# object technically is not null.

    这篇关于为什么ReSharper不建议对这两个块都使用空传播?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆