【问题标题】:Non-changed value and auto-implemented properties未更改的值和自动实现的属性
【发布时间】:2017-11-22 15:41:00
【问题描述】:

在实现简单属性时,可以使用auto-implemented properties,让代码看起来更简单,像这样:

public int MyInt
{
    get; set;
}

或者您可以使用“手动”私有字段来实现它。在这种情况下,我经常看到人们在使用set 之前检查值的变化。像这样:

private int _myInt;

public int MyInt
{
    get { return _myInt; }
    set 
    {
        if value != _myInt
            _myInt = value;
    }
}

所以我的问题是:检查更改的值(在后一种情况下)对任何事情都有好处吗?如果是,那么这对自动实现的属性有什么影响?

【问题讨论】:

  • 您可以进行简单的验证。
  • 在我看来,属性的 setter 或 getter 方法中不应该有任何逻辑。并建议使用 Auto 属性。
  • 只是一个旁注,它被称为“私有领域”,而不是“私有财产”。公共属性使用私有字段。
  • 你要在实现INotifyPropertyChanged的时候做那个检查,否则就没用了。
  • @Dennis_E 有趣的是你应该提到它。想想看,我在这个话题上所做的大部分阅读都与INotifyPropertyChanged有关。

标签: c# properties


【解决方案1】:

你不能两者都做,使用自动实现的属性并检查它的值。只要您将任何逻辑引入 getter 或 setter,它就不再是自动实现的属性。

auti-implementing 属性只是 getter/setter 访问私有后备字段的语法糖,就像您要这样写:

public int MyInt
{
    get { return _myInt; }
    set { _myInt = value; }
}

当您想检查新值是否有效时,您必须使用带有某些逻辑的设置器。例如,您可能想检查您的整数是否为正,因为您的应用程序无法处理负值。因此,您只需在 setter 中引入该检查即可。

set 
{
    if (value >= 0)
        _myInt = value;
}

顺便说一句,您不能只定义一个部分(即getter setter),您必须用大括号定义两者。另一方面,您当然可以完全省略其中一个,使您的属性只读或只写(尽管我几乎想不出后者的任何用途)。实际上,即使是属性也是 get- 和 set- 方法的语法糖。因此,您可以将它们视为常用方法。你为什么不应该在那里引入任何逻辑?当然,属性往往会让人们认为在他们的 setter 或 getter 中没有发生什么特别的事情,这也是约定所建议的。然而,实际上它们并没有什么特别之处,除了在自动实现属性上,您只是访问一个您无法在代码中访问的支持字段,因为 IDE 不知道它的名称,但是它存在在 IL as shown here 内。

编辑:回到你的问题。如果您在 setter 中或之前引入验证新值的逻辑,这不会产生真正的影响,因此您也可以这样写:

int newValue = -1;
if(newValue >= 0)
    myInstance.MyInt = newValue;

但这可能会非常混乱,尤其是当您需要在代码中的其他位置设置属性并再次检查时,就会破坏DRY-priniciple。所以最好这样做once, and only once(在setter中)。

【讨论】:

  • 您可能应该更仔细地阅读这个问题。您的回答似乎与问题无关。
  • @RacilHilan 这个问题是基于一个错误的假设,即自动实现的属性可以与验证结合使用。我清除了这一点并表明它们实际上只是方法。
  • 嗯,我再次阅读了这个问题,没有看到任何可能的错误假设。也许我看不到你看到的。
  • @RacilHilan 那么“如果是这样,那么这对自动实现的属性有什么影响”?这意味着我们可以将验证与 AI 属性一起使用,不是吗?
  • 不一定。但可能。我承认那句话含糊不清,不确定OP的意思。让我们看看 OP 是否会对您的答案发表评论。无论如何,你仍然没有回答主要问题,所以你的编辑很好。
【解决方案2】:

检查更改的值(在梯形图的情况下)是否有用?

并非如此,至少在您提供的示例中不是。好吧,除非您有代码在一个巨大的循环(数十万)中分配给该属性,在这种情况下,如果检查该值比分配快几毫秒,那么您将看到明显的差异。我说“如果”,因为我不确定int 的情况,所以如果您对答案感兴趣,就必须对其进行测试。

但是,在其他情况下,可能会有明显差异。例如,如果 setter 不仅仅是分配值。

【讨论】:

    【解决方案3】:

    假设MyInt 是您鼠标的X 位置,您有一个无限循环,每毫秒获取鼠标位置,并显示在窗口上。如果你不检查你必须每毫秒更新一次窗口,当你的鼠标静止时。

    大部分情况你不需要检查,即使是相同的value,值也会改变。当您遇到性能问题时执行此操作。

    【讨论】:

    • 这是一个很好的例子,但您假设分配比检查慢。我不确定情况是否如此,至少对于简单类型而言并非如此。但是如果属性是复杂类型并且检查只是读取它的一部分,那么这可能是一个很好的例子。
    • 很好的例子。您能否指出(为了其他人阅读本文)此示例所需的验证意味着您应该使用“手动”方法?
    【解决方案4】:

    当你实现INotifyPropertyChanged时你会使用那个检查
    (您只想在属性值实际发生变化时触发事件,而不仅仅是在调用 setter 时。)

    【讨论】:

    • +1 但您可能想删除最后一句话。正如您从其他答案中看到的那样,它在其他一些情况下可能很有用。
    • 虽然我已将此答案标记为已接受,但我强烈建议阅读所有答案。在这篇文章中可以找到很多重要的观点。感谢所有参与的人。
    猜你喜欢
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多