在Unity(Unity5)中的C#属性 - 是否可以避免备份变量?

4

在Unity5中(很难确定正在使用的c# / Mono / .Net版本),我们会像这样精确地处理属性:

private int _distance;
public int Distance
    {
    private set
        {
        _distance = value;
        controls.Blahblah(_distance);
        }
    get
        {
        Debug.Log("hah!);
        return _distance;
        }
    }

但是考虑一下c#中的新"自动属性",它们似乎像是:

 public int Distance {get; set;}   // ?

但是我不知道如何在getter/setter中“做一些事情”?

换句话说,有没有办法在“手动”创建属性时自动生成备份变量(以及方便性 - 使其保持私有)?

重申一遍,因为这被标记为重复问题,如何在自动Property习语中的getter/setter中“做一些事情”...

...或者反过来...

如何隐藏、摆脱或自动提供backer,如果你编写自己的“手动”属性?

请注意,当然你或另一个程序员可以意外触碰下划线后备变量:有没有任何方法完全避免这种情况?


1
如果你需要添加更多的代码,那么你做得很对。自动属性中不能有额外的代码,它只是一种简写方式。 - Blue Eyed Behemoth
2
“自动属性”只是对显式后备字段所做的事情的语法糖,因此没问题。(与自动属性的主要区别在于,后备字段对您隐藏,您无法编写任何代码来响应读取或写入属性。) - Matthew Watson
1
这个问题与Unity无关,应该删除标签。 - sara
1
那我纠正自己的错误 :) - sara
1
@JoeBlow 你说得对,它确实在编译器方面做了很多工作。 - Blue Eyed Behemoth
显示剩余7条评论
4个回答

3

如果您想在getter/setter中执行除了仅分配给字段之外的“某些操作”,则不能使用自动属性。对于您的示例代码描述的用例,自动属性不是一个选项。具有显式备份字段没有任何问题。


啊..讲解得非常好,谢谢Kai。你能否澄清一下:关于后备变量:在我的例子中是否有一种方法可以“摆脱”后备变量?(这样的后备变量存在很多问题:例如,如果它在其他地方被意外触碰会怎么样。)无论如何,现在是否有一种方法可以在我的例子中“摆脱”后备变量?谢谢! - Fattie
1
不行,你必须接受它。你可以通过约定仅通过明确定义的方法/属性访问来操作字段来减轻风险。通常,这是通过确保团队中的每个人都知道“规则”并进行代码审查来强制执行的。 - sara
很高兴听到这个被证实了!你太棒了,Kai。 - Fattie
有没有使用自动属性而不是字段的理由?我只看到反射和代码统一是唯一的原因,但它们对我来说不够好。出于安全原因,我习惯于使用公共字段而不是公共自动属性,因为这是相同的解决方案。 - Jerry Switalski
一个(不太令人信服的)论点是“未来扩展更容易”,但你的IDE可以为你处理这个问题。另一个是调试断点。我认为最好的一个是能够指定一个公共getter和一个私有setter。我认为具有公共setter的自动属性是一种反模式,应该像公共字段本身一样被避免。 - sara
显示剩余6条评论

3

如果你只有私有变量而没有其他逻辑,那么可以使用自动属性。

Class Something something
{
    public int Distance
    {
    private set
     {
       _distance = value;
     }
    get
     {
       return _distance;
     }
    }

// Keep this at the end of the class
// In visual studio you can collapse region and wont attract
// attention/distracting in your editor.

#region data members
private int _distance;
#endregion data members
}

你可以把它替换为public int Distance {get; set;}

但如果你想执行其他操作,比如记录日志,那么你必须以传统方式编写。

编辑

这都是编码习惯。我通常会在#region p ... #endregion中包含私有变量。并只使用属性设置-距离,从未使用过 _distance。这更多是编码习惯而不是实际解决方案。

我这样做的另一个原因是——在WPF中,每当我们设置属性时,我们需要调用NotifyPropertyChanged事件。如果我不使用属性名,则会出现错误。所以这种使用属性而不是私有变量的习惯一直保持着。

你无法使变量无法发现,只能将它们组合在一起以便更易读,这是人为实施的惯例。


在文件中查找... ._。除非您在某个地方使用了 object._variable,否则不应该返回任何结果... - Pimgd
嘿,抱歉让你感到困惑。它仍将在整个课程中可用。 - Carbine
您可以在 Visual Studio 编辑器中折叠区域,这样当您阅读代码时就可以隐藏不需要的混乱。 - Carbine
1
#region 不应该像这样被滥用 - Mathieu Guindon
@Mat'sMug 顺便说一下,我早就读过这篇文章了。虽然这篇文章在重构方面有些有效的观点,但对于我来说,使用区域来隐藏代码中的样板代码是完全合理的,因为它们会使代码变得混乱。这是主观的,但我倾向于在这种情况下使用区域。在上述场景中,你需要一个不可避免的私有变量,而这会导致代码混乱。 - Carbine
显示剩余2条评论

2

自动属性不允许您在其中执行“任何”操作。它们只是以下缩写:

public int Distance
{
    get
    {
        return _distance;
    }
    set
    {
        _distance = value;
    }
}
private int _distance = default(int);

在这个属性中使用实际变量没有任何问题,不会影响任何内容。

需要记住的一件事是,如果您想在编辑器中编辑一个变量,则不能使用属性。您将需要公开一个公共字段:

public int Distance;

关于检查器变量,这是一个很棒的观点。在这种情况下,我们可以使用另一个普通的检查器变量,并使用 void OnValidate() 从中设置相关属性,以解决开发过程中需要从检查器设置属性的问题。这非常实用。 - Fattie
1
或者你可以通过[SerializeField]将私有字段公开。 - benscabbia

1
如果您的get和set需要有额外的代码,比如用于日志记录,那么您必须按照第一种方式实现它们。如果您只需要获取和设置值,则自动实现属性更好,也就是第二种方法。

谢谢Ehsan...正如你所看到的,我只是在检查...有没有办法在示例代码中“摆脱”后备变量? - Fattie
@JoeBlow,你可以使用自动实现属性,在第二个代码块中有这种属性。 - Ehsan Sajjad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接