【问题标题】:Should properties in C# perform a lot of work? [closed]C# 中的属性是否应该执行大量工作? [关闭]
【发布时间】:2011-02-16 14:46:11
【问题描述】:

当一个属性被读取或分配给它时,人们不会期望它执行大量工作。当使用 setSomeValue(...)getSomeValue(...) 方法时,人们不应该对引擎盖下可能发生的一些不平凡的事情感到惊讶。然而,既然 C# 提供了 Properties,那么使用 getter 和 setter 方法来代替似乎很愚蠢。你对此有什么看法?我应该将此 Q 标记为社区 wiki 吗?

谢谢。

编辑:

在我的情况下,调用并不昂贵,但它会触发在另一个类中设置相关属性,并可能将一条短消息写入日志文件(如果 URL 为空白)。物业工作量太大了吗?有什么选择。

【问题讨论】:

  • “另一个类中的相关属性”是否被属性设置器或-getter更改?
  • 它被一个属性改变了......它实际上变得更奇怪了。最顶层的属性来自一个 .config xml 文件,并由一个 XML [de]serializer 填充。这可能让我别无选择。我很高兴我问了这个问题,考虑这些事情很好。

标签: c# properties


【解决方案1】:

然而,既然 C# 给了世界 属性,用起来好像很傻 取而代之的是 getter 和 setter 方法。

在考虑属性应该有多昂贵之前,我建议您考虑一下您正在建模的概念是否最好表示为“某物的属性”。 语言中存在属性来表达其他实体的归属 - 如果 SomeValue 在逻辑上不是它所属类型的属性,那么您应该考虑改用 getter/setter 方法。

C# 中的属性应该执行很多操作吗 工作吗?

话虽如此,如果可能的话,它有助于使属性变得便宜。 大多数开发人员希望属性能够有效地包装它们所属类型的某些内部状态。违反此期望会使开发人员更难编写使用该属性的性能良好的代码。例如,如果一个属性被用作for 循环的条件,它将在每次迭代时进行评估——如果它很昂贵……那可能很糟糕。

属性也经常在调试器中访问 - 您不希望属性执行昂贵的逻辑,因为这会抑制调试。执行具有副作用的操作(例如查询数据库)的属性 getter 通常也是一种不好的做法,因为它们可以在调试器中检查应用程序的行为时引入 heisenbugs

有什么选择。

您可能还想阅读this answer,它为物业设计提供了一些很好的通用指南。我还建议您阅读 MSDN 上的 .NET 设计指南中的 Choosing Between Properties and Methods

有时创建一个只读属性(无设置器)是有意义的,但其中存在一个或多个单独的方法来设置与该属性相关的内部状态。是否使用这个习惯用法取决于对对象的操作是在语义上暴露为“改变状态”还是“执行活动”。如果是后者,我倾向于使用方法(而不是属性设置器)来表达这种行为。

【讨论】:

【解决方案2】:

一般的经验法则是调用属性不应该很昂贵。如果调用它们的成本很高,请将它们改为吸气剂。这不能总是遵循,你肯定需要使用判断。

【讨论】:

  • Hm ...在我的情况下调用并不昂贵,但它会触发在另一个类中设置相关属性并可能将一条短消息写入日志文件(如果 URL 为空白)。物业工作量太大了吗?有什么选择?
  • @Hamish Grubijan 如果您在课堂上公开正确命名的操作/方法,通常会更清楚。特别是正如您所提到的,它还有其他一些潜在的影响。
【解决方案3】:

工作量太大的确切数量值得商榷。最好的答案是属性应该执行更少的工作而不是更多的工作:)

Get Properties 不应该做的一件事是改变对象的状态。

【讨论】:

  • +1 表示 get 不改变对象的状态...是的,我已经看到了 - 那里有噩梦代码的闪回
  • 是的,在调试器监视列表中找一个这样的虫子,你会被扯掉的。
  • 哇,我可以想象那会有多臭。并不是说我会有意识地尝试想出一个改变状态的吸气剂,但想想很有趣。
【解决方案4】:

使用方法代替,人们不应该对某些不平凡的事情可能在幕后发生感到惊讶

由于 Properties 只是完全相同的 Set... 和 Get... 方法(由编译器在生成 IL 时生成)的语法糖 - 没有任何区别。如果你想在 SetFoobar 中实现一些逻辑 - 在 Foobar { set { ... } } 中也这样做

【讨论】:

    【解决方案5】:

    使用您创建的类的人不知道实现是什么。他可能会一遍又一遍地使用 User.ID,却不知道其中的每一个都是数据库调用。
    你看,在 99% 的情况下,属性只不过是带有额外代码行的变量,因此开发人员将它们视为这样。如果以任何方式昂贵,将属性重构为方法被认为是一种好习惯。你永远不知道一个方法隐藏了什么,(优秀的)开发人员在可以缓存以前调用的结果时会节省调用方法。

    【讨论】:

      【解决方案6】:

      不,属性不应该执行很多工作......

      【讨论】:

      • 请详细说明。我认为软件工程中没有确切的规则。一定有一些灰色地带。甚至定义什么是“大量工作”和什么是“一些工作”也很棘手。
      【解决方案7】:

      “应该”他们?这是一个棘手的问题。

      他们当然可以,而且没有“很多”理由不这样做。堆栈溢出是避免在属性访问器中做大量工作的一个很好的理由,但是如果您的代码在其他方面是可读的并且您的意图很容易传达,那么没有硬性规定可以禁止。

      【讨论】:

        【解决方案8】:

        属性实际上只是syntactic sugar。作为最佳实践,我喜欢让它们保持非常简单,而不是在其中放入大量代码。但是,没有技术原因。最后,它们只是被执行的函数。当你使用它们时,你需要问的是,对于那些追随你的人来说,什么是最易于维护和最直观的。

        【讨论】:

        • 漂亮的 cmets 有时会弥补丑陋的代码。我正在考虑在调用这个特定属性的地方添加 cmets(目前只有一个地方),并警告说需要做一些额外的工作。
        • 好点。但归根结底,您可能仍然有难以维护的丑陋代码。我会谨慎行事。
        【解决方案9】:

        作为一个类的用户,我希望属性不会很昂贵 - 因为顾名思义,它们只是获取/设置对象的值。相反,当我在对象上调用方法时,我知道它会“做某事”并且可能很昂贵。

        对于属性应该始终正确的一件事是,property-getter 应该没有副作用。例如。一个属性获取器应该返回相同的值,即使我连续调用它 10 次。当您看到属性的这种用法时,这一点最明显:

        int result = obj.SomeNumber + obj.SomeNumber;
        // I expect SomeNumber to return the same value on both calls
        

        【讨论】:

        • 副作用更多的是属性对对象的作用,而不是属性返回的值。例如,在 GUI 框架中,触摸一个属性可能会导致创建控件的窗口句柄。这是一个副作用。
        • 很容易让我相信属性的 getter 部分不应该有副作用并且应该返回相同的东西。我不确定 setter 属性是否必须遵守相同的规则。也许某些参数在整个程序执行过程中只能设置一次,然后应该抱怨。
        • @Hamish:当然,这主要(仅)对财产获取者有效。更正了答案。
        【解决方案10】:

        我认为最好的规则是它们不应该抛出异常,也没有副作用。例如,如果您继续调用 getter,并且没有其他任何更改,则返回的值不应更改。请注意,“DateTime.Now”不遵循此规则,但可能应该遵循。

        【讨论】:

        • setter 可以抛出异常吗?如果几率很小怎么办?与 Java 不同,.Net 不会强制您捕获所有异常,因此这可能至少部分是模棱两可的。
        • setter 和 getter 都可以做到。框架设计指南说:避免从 getter 抛出异常并且:如果属性设置器抛出异常,则保留之前的值
        • 但是 .NET 避免了这个规则:IsSecurityCritical 可以抛出 NotSupportedException: msdn.microsoft.com/de-de/library/…
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-26
        • 2010-09-13
        • 1970-01-01
        相关资源
        最近更新 更多