【问题标题】:Use of properties vs backing-field inside owner class在所有者类中使用属​​性与支持字段
【发布时间】:2010-03-16 18:21:43
【问题描述】:

我喜欢 C# 中的自动实现属性,但最近我的隔间里站着一头大象,我不知道该怎么处理它。

如果我使用自动实现的属性(以下简称“aip”),那么我将不再有可在内部使用的私有支持字段。这很好,因为 aip 没有副作用。但是如果以后我需要在 get 或 set 中添加一些额外的处理呢?

现在我需要创建一个支持字段,以便扩展我的 getter 和 setter。这对于使用该类的外部代码来说很好,因为它们不会注意到差异。但是现在所有对 aip 的内部引用都会在访问属性时调用这些副作用。现在必须重构对曾经 aip 的所有内部访问以使用支持字段。

所以我的问题是,你们大多数人都做什么?您是使用自动实现的属性还是更喜欢始终使用支持字段?您如何看待具有副作用的属性?

【问题讨论】:

  • 是的,我知道人们以前也问过类似的问题。我确实使用了谷歌,以及专门搜索 StackOverflow,但我没有找到明确/令人满意的答案。所以我用自己的话提出了这个问题。

标签: c# properties automatic-properties


【解决方案1】:

Eric Lippert has an excellent blog post 回答了这个问题:

如果动机的原因 从自动实施更改 明确实现的属性 属性是改变语义 那么你应该 评估是否需要语义 当从 类内相同或 与期望的语义不同 当从 课外。

如果该调查的结果是 “在课堂上,想要的 访问此属性的语义 与想要的不同 访问属性的语义 从外部”,那么您的编辑有 引入了一个错误。你应该修复 漏洞。如果它们相同,那么您的 编辑没有引入错误;保持 实现方式相同。

【讨论】:

  • 虽然我一直是 EL 博客链接的粉丝,但这个答案实际上并没有告诉发帖人。他假设的情况是逻辑不同的;这不是他必须问自己的问题。
  • 我非常不同意 - 这是一个语义问题,如果您需要直接使用支持字段而不使用属性,而您之前不需要这样做,那么您正在破坏某些东西。
  • 他的场景是他正在改变 getter 的语义。他已经说过他正在破坏某些东西,因为他不希望他的内部逻辑受制于添加到 getter 中的任何内容。他的问题是“在这种情况下我该怎么办?”,而你的大部分引文都是关于做出这个决定。
  • 实际上,这在我脑海中已经存在很长时间了,并不是因为我目前正在做任何特定的代码更改。这是预防性研究,因为我正在开始一个新项目并试图“正确”地做事。自 C#3.0 以来,我一直使用 AIP,但我的大多数同事都没有。我继承了许多可以从使用 AIP 中受益的代码,但我想知道是否有充分的理由不这样做。所以我只是在征求意见。
【解决方案2】:

首先,property getter 不应该有副作用。情况并非总是如此,但您应该有充分的理由不这样做。

也就是说,获取对属性的引用列表很简单。如果您更改为显式属性并希望您的私有代码访问您的新支持变量,那么修改应该相当容易。

【讨论】:

  • 这真的只适用于get;边。套装;根据定义,side 有副作用。
  • 我对副作用的理解是每次调用 getter 时都会更改支持字段。即得到 { _field++; }。但是当你想要触发像 OnPropertyChanged() 这样的事件时呢?这被认为是副作用吗?如果您的内部逻辑需要对您的支持字段执行三个数学运算以获得最终值,您当然不希望 PropertyChanged 事件触发三次。
  • 副作用也很有用:延迟加载。
  • @whatispunk:这是一个指导方针;延迟加载显然是一个例外,但用户应该知道,获取属性可能可能是一项昂贵的操作,因为属性是/本来是非常轻量级的,重量级操作转移到方法中。话虽如此,恕我直言,获取属性值不应在同一对象上引发 PropertyChanged 事件,也不应(理想情况下)影响另一个属性的值,因为 order 在其中访问或设置属性。
  • 你是对的。我真的没有考虑清楚。 Getter 永远不会调用 OnPropertyChanged。
【解决方案3】:

我认为使用自动实现的属性没有任何问题。假设你有一些财产:

public string Name 
{
    get; set;
}

如果您将来需要一些额外的处理,您只需修改您的属性:

private string name;

public string Name 
{
    get { return this.name; }
    set 
    {
       if (!string.IsNullOrEmpty(value))
       { 
           this.name = value;
       }
    }
}

【讨论】:

  • 问题是在进行此更改时要做什么(或如何计划)在类中引入了额外的(不希望的)逻辑,而不是如何进行更改。
【解决方案4】:

就从问题中分离命令而言,具有副作用的属性并不是那么好。我希望我的对象以相同的方式回答问题,只要我没有调用任何明确说明某些事情可能会改变的方法。

【讨论】:

    【解决方案5】:

    在需要支持字段之前,我总是使用 AIP。只是交换并不难:

    public string MyString{get;set;}
    

    private string myString;
    public string MyString{get{return myString;} set{myString = value;}}
    

    我认为总是对后者来说是不必要的混乱。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-26
      • 2014-10-09
      • 1970-01-01
      • 2019-12-20
      • 2017-04-26
      • 2013-05-06
      • 1970-01-01
      • 2021-12-02
      相关资源
      最近更新 更多