地产设计

注释

此内容由 Pearson Education, Inc. 的许可从 框架设计指南:可重用 .NET 库的约定、习惯和模式(第 2 版)重新打印。 该版于2008年出版,此后该书已于 第三版全面修订。 此页上的一些信息可能已过期。

尽管属性在技术上与方法非常相似,但它们在使用方案中大相径庭。 它们应被视为智能领域。 它们兼具字段的调用语法和方法的灵活性。

✔️ 如果调用方不应更改属性的值,请创建只能获取而不能修改的属性。

请记住,如果属性的类型是可变引用类型,即使该属性是仅获取属性,也可以更改属性值。

❌ 请勿提供仅限设置的属性,或设置器比获取器具有更广泛可访问性的属性。

例如,不要定义具有公共 setter 和受保护 getter 的属性。

如果无法提供属性 getter,请改为以方法的形式实现该功能。 请考虑将方法名称以 Set 开头,然后按照您会命名属性的方式进行命名。 例如,AppDomain 有一个称为 SetCachePath 的方法,而不是一个仅设置属性名为 CachePath 的属性。

✔️ 请为所有属性提供合理的默认值,确保默认值不会导致安全漏洞或非常低效的代码。

✔️ DO 允许按任意顺序设置属性,即使这会导致对象的临时无效状态。

同一对象上的两个或多个属性通常会相互关联,以至于某个属性的某些值在考虑其他属性的值时可能无效。 在这种情况下,由于无效状态导致的异常应推迟到对象实际使用相关属性为止。

✔️ 如果属性 setter 引发异常,请保留以前的值。

❌ 避免在属性读取器中引发异常。

属性访问器应该是简单的操作,不应有任何前置条件。 如果 getter 可以引发异常,它应该重新设计为方法。 请注意,此规则不适用于索引器,在索引器中,我们期望异常作为验证参数的结果。

索引属性设计

索引属性是一个具有参数的特殊属性,可以使用类似于数组索引的特殊语法调用。

索引属性通常称为索引器。 索引器应仅在提供对逻辑集合中的项的访问权限的 API 中使用。 例如,字符串是字符集合,添加了索引器 System.String 以访问其字符。

✔️ 请考虑使用索引器提供对内部数组中存储的数据的访问权限。

✔️ 请考虑为表示项集合的类型提供索引器。

❌ 避免对多个参数使用索引属性。

如果设计需要多个参数,请重新考虑该属性是否真的表示逻辑集合的访问器。 如果不是,请使用其他方法。 请考虑使用GetSet作为方法名称的开头。

❌避免使用参数类型是System.Int32System.Int64System.StringSystem.Object或枚举以外的索引器。

如果设计需要其他类型的参数,请强烈重新评估 API 是否真的表示逻辑集合的访问器。 如果没有,请使用一种方法。 请考虑使用GetSet作为方法名称的开头。

✔️ 请对索引属性使用 Item 作为名称,除非有明显更好的名称(例如,请查阅 System.String 上的 Chars[] 属性)。

在 C# 中,索引器默认命名为 Item。 IndexerNameAttribute可用于自定义此名称。

❌ 请勿同时提供索引器和语义上等效的方法。

❌ 请勿在一种类型中提供多个重载索引器系列。

这由 C# 编译器强制实施。

❌ 请勿使用非默认索引属性。

这由 C# 编译器强制实施。

属性更改通知事件

有时,提供通知用户属性值更改的事件非常有用。 例如,System.Windows.Forms.Control在属性TextChanged的值发生更改后引发事件Text

✔️ 在修改高级 API(通常是设计器组件)中的属性值时,请考虑引发更改通知事件。

如果视为有一个适合用户了解对象属性何时发生变化的场景,则对象应该为该属性引发更改通知事件。

但是,为低级别 API(如基类型或集合)引发此类事件不太可能值得开销。 例如, List<T> 将新项添加到列表和 Count 属性更改时,不会引发此类事件。

✔️ 考虑在属性值因外部因素更改时引发变更通知事件。

如果属性值通过一些外部力更改,(而不是通过调用对象的方法),会触发事件来通知开发人员该值正在更改和已经更改。 一个很好的示例是 Text 文本框控件的属性。 当用户在 TextBox 中键入文本时,属性值会自动更改。

部分内容 © 2005, 2009 Microsoft 公司。 保留所有权利。

经皮尔逊教育有限公司许可,从由 Krzysztof Cwalina 和 Brad Abrams 撰写的《框架设计准则:可重用 .NET 库的约定、习惯和模式》一书中重新印刷。此书由 Addison-Wesley Professional 于 2008 年 10 月 22 日出版,是微软 Windows 开发系列的一部分。

另请参阅