Field vs { get;set } vs { get=>field; set=>field = value;} - C# Unity

问题描述

我有这段代码,我的目标是修改要在抽象类中的任何方法中使用的字段值。 我的理解是:

  • 您可以创建一个字段(例如 private int speed
  • 创建属性修改其值(public int Speed {get;set;}public int Speed {get => speed ; set => speed = value;}

但是编辑器(那里没有修改变量,它是硬代码)不会抛出预期的结果,而是修改 speed 字段值。 一个清晰和简洁的解释表示赞赏。

enter image description here

解决方法

在您的代码中,fireRateFireRate 是完全独立的字段/属性以及 speedSpeed。修改 fireRate 不会影响 FireRate,反之亦然。

SerializeField 用于序列化字段而不是属性。在这两种情况下,只有字段(fireRatespeed)被序列化。

试试下面的代码:

    [SerializeField] public int a;
    [SerializeField] public int b { get; set; }
    [SerializeField] public int c => a;

Unity 默认不会序列化属性,只会序列化 a

,

您混淆了术语 "field""property"。属性可以在 getter 和 setter 中实现额外的行为。

首先:Unity 做了not serialize properties

这将 Unity 中属性的用途限制为运行时。

所以大多数时候会想要一个像

这样的模式
[SerializeField] private int a;
public int A => a;

这例如其目的是您可以通过编辑器分配值,由类本身对其进行编辑,但仅允许其他人只读访问 => 封装。

当然,为了完整性,它可以执行额外的健全性检查,例如

private const int min = -3;
private const int max = 17;
private bool allowSet;

[SerializeField] private int a;
public int A 
{
    get => a;
    set 
    {
        if(allowSet) a = Mathf.Clamp(a,min,max);
    }
}

几乎不需要自动属性(在我看来)除非你想直接限制访问

public int b { get; private set;}

这仅允许此类写入,但其他所有人都可以读取此值

因此,什么时候有用是主观的,取决于具体情况。


现在查看您的代码,Speed - speedFireRate-fireRate 之间绝对没有关系!它们是完全独立的字段和属性。

这里的混淆可能是由于 Inspector 创建的显示名称。它会自动使所有字段名称大写,以便

[SerializeField] private int _example;

将显示为 Example

你很可能只会选择

[SerializeField] protected float Speed;
[SerializeField] protected float FireRate;