在属性中实现逻辑是一种好的做法

时间:2010-05-27 16:52:18

标签: c# asp.net

我们使用ASP.NET和C#并基于我通过的开源项目/文章,我发现许多属性都包含逻辑,但是当我这样做时,团队负责人告诉我它不是擅长将逻辑放在属性中,但通过方法调用逻辑......

真的很糟糕吗?为什么不在属性中使用逻辑呢?

感谢,

8 个答案:

答案 0 :(得分:37)

预计属性访问是即时的(没有长时间等待),一致(没有变化的值)和安全(没有例外)。如果你能做出这些保证,我认为在属性中加入逻辑是可以的。

答案 1 :(得分:30)

在属性中包含一些逻辑很好。例如,setter中的参数验证和getter中的延迟计算都很常见。

通常对于属性访问做一些昂贵的事情(例如数据库调用)是一个坏主意。开发人员倾向于认为评估属性相当便宜。

这最终是一个判断调用 - 但我当然拒绝了这样的建议,即属性应该只能通过自动属性来实现。

答案 2 :(得分:9)

Properties are methods。它们只是吸气者/制定者的捷径。任何在getter / setter中有效的逻辑都适合放入属性。通常不会放入getter / setter的任何逻辑都不适合放入属性。一般来说,如果您(作为该类的消费者)不能过分地期望设置属性值,或者更糟糕的是,获取属性值可能会导致行为发生,那么该逻辑可能属于其他地方。换句话说,逻辑应该与获取或设置属性相关并且一致。

引用上面的链接文章:

  

属性是提供的成员   灵活的读,写或者机制   计算私有字段的值。   属性可以像它们一样使用   是公共数据成员,但他们是   实际上称为特殊方法   存取。这样可以实现数据   在提供的同时轻松访问   方法的安全性和灵活性。

答案 3 :(得分:4)

一个常见的答案适用于此:它取决于。

通常,在getter和setter中实现 business 逻辑不是一个好主意。如果您的对象是简单的DTO(数据传输对象),则会违反单一责任。

但是,状态跟踪逻辑和其他内务管理通常在属性中找到。例如,Entity Framework 4自跟踪实体在每个原始属性设置器中都具有状态管理逻辑以允许跟踪。

属性中逻辑的替代方法是面向方面编程(AOP。)使用AOP,您可以在对象和托管过程之间“注入”逻辑。可以“拦截”对象的访问并有条件地处理。

答案 4 :(得分:2)

如果您需要使用JSon,XML或ORM序列化/反序列化对象,那么将业务逻辑放置在setter中会让您遇到麻烦。这种情况的一个示例可能是使用NoSql数据存储区(如文档数据库或ORM)。其中一些(例如NHibernate)可以配置为访问支持字段而不是setter。

我发现使用公共Getter和Private setter以及根据需要使用附加逻辑设置值的方法是一种很好的方法。大多数序列化程序都可以访问私有setter,因此您最终得到的是对持久化对象的准确表示,而不会意外地触发逻辑,这可能会在反序列化时错误地更改值。

但是,如果您认为不需要序列化/反序列化,那么这不应成为问题。

答案 5 :(得分:1)

在我看来,这绝对没问题。我看待它的方式,首先将属性作为语言特性的唯一理由是你可以在其中包含逻辑。否则,您也可以只允许直接访问基础数据成员。

答案 6 :(得分:0)

通常,属性仅影响1个变量,因为它主要是为了这个目的而制作的。但有时候,你想要一个更高级别的属性,而不仅仅是一对一的变量。因此,在这种情况下,它将包含代码是正常的。但是你必须记住,一个属性不是像函数一样使用。当你调用一个函数时,你知道它会进行一些处理。当你打电话给一个房产时,你预计它会很快。

但最后,这是一个偏好问题,就像编码标准一样,跟随你的上司告诉你的是由你自行决定。所以它并不坏,取决于你的判断。

答案 7 :(得分:0)

在我看来,只有在某些情况下才允许在Setter / Getter中使用业务逻辑。对于exaple:它被赋予了负责验证输入的逻辑,因为setter负责维护对象状态,因此不应该违反状态。因此,您应该将业务逻辑切割为仅负责一个主题的代码的最小部分。

另一件事是你的班级应该(在最好的情况下)POCO。为什么?因为它应该是可重用的,并且当类包含属性中的逻辑时,可以简单地阻止可重用性。认为您在属性中有SqlServerPerson一些SQLServer验证,那么当您更改ORM / DB访问权限时,很难用例如NHibernatePerson替换它。