Unity封装,属性逼我重写变量名?

Unity Encapsulation, property force me to rewrite variables names?

我想了解一个简单的东西。

我正在阅读很多关于在 Unity 和 C# 中封装的问题和答案。 都在谈论 get/set 并且大多数答案都是这样说的 getset 的最大好处是停止输入错误或我在任何其他脚本中编写的东西来访问我的变量并给我的程序带来问题。

所以,如果我真的很专注并且我没有犯 get/set 变成 null 这样的错误!我的意思是,没有其他真正的好处。

此外,我看到 属性 强迫我重写变量名称,所以

像这样:

private int health 
public int health { get; private set; }

所以结果是我编写了更复杂的代码。我在脚本中使用了更多相同的名字,这不危险吗?

您的示例无效,因为 health 是同一个变量两次。常见的约定是对支持字段使用 _healthhealth,对 属性 (get/set/) 使用 Health。此外,没有什么能阻止你做:

private int backingField;
public int OtherProperty { get { return backingField; } } 
public int Property => backingField; // Does same thing as above

这只会让你、你未来的自己和你的同事感到困惑。

但是,对于您的情况,您可以这样做:

public int Health { get; private set; }

So, if I am really focused and I don't make a mistake

这是一种真的糟糕的心态。如果你继续这种心态,你会搬起石头砸自己的脚,因为你无法同时专注于所有事情。大脑一次只能加载这么多信息。这个想法是不允许自己犯错误。

我的程序员教授曾经说过,这种心态就像把你的孩子留在高速公路的一个车道上,如果有车来,你就把它移到另一条车道上。你可以永远这样做,或者你不能在高速公路附近的任何地方生孩子。

Visual Studio 使重命名变得非常容易,而且您只需要这样做一次。 get/set 更好的功能是确保数据有效。例如

private int _age = 0;
public int Age
{
    get => _age;
    set
    {
        if (value > 0)
            _age = value;
    }
}

此代码将阻止用户将 Age 设置为负数,因为那是不可能的。

属性很棒,您可以用它们做很多很酷的事情,例如:

public struct Rectangle
{
    public int X, Y;
    public int Area => X * Y;
    
    public Rectangle(int x, int y) => (X, Y) = (x, y);
}

public int Area => X * Y; 是一个 属性,虽然看起来不像。等同于:

public int Area
{
    get
    {
        return X * Y;
    }
}

很酷的是 Area 只有一个 getter 因此它的值无法更改。 Area = 3 将不起作用。这是理想的,因为那样会使数据无效。

实际上,所有 Area 都是方法 GetArea() => X * Y; 的语法糖,但我们不使用 Get 前缀或末尾的 ()

属性什么时候有用

总而言之,属性 (get/set) 可用于将变量设置为私有或受保护,以防止无效数据泄漏,当 setter 用于使确保新数据有效,或者有一些看起来像只读变量但实际上执行快速计算以获取数据的东西。

从这个意义上说,它们非常适合封装。

编辑: 正如 Draco18s 指出的那样,它们对接口也很有用,就像 类,但其中一个区别是它们不能有字段.但是,它们 可以 具有属性,因为在幕后,属性只是方法。

一般情况下,Property值名称会大写。该领域将是 小写.

通常 field 设置为私有供 class 使用。

Property 将在编译代码时转换为 Get()Set(value) 方法。

private int _health 
public int Health { get; private set; }