注释
此内容由 Pearson Education, Inc. 的许可从 框架设计指南:可重用 .NET 库的约定、习惯和模式(第 2 版)重新打印。 该版于2008年出版,此后该书已于 第三版全面修订。 此页上的一些信息可能已过期。
尽管属性在技术上与方法非常相似,但它们在使用方案中大相径庭。 它们应被视为智能领域。 它们兼具字段的调用语法和方法的灵活性。
✔️ 如果调用方不应更改属性的值,请创建只能获取而不能修改的属性。
请记住,如果属性的类型是可变引用类型,即使该属性是仅获取属性,也可以更改属性值。
❌ 请勿提供仅限设置的属性,或设置器比获取器具有更广泛可访问性的属性。
例如,不要定义具有公共 setter 和受保护 getter 的属性。
如果无法提供属性 getter,请改为以方法的形式实现该功能。 请考虑将方法名称以 Set
开头,然后按照您会命名属性的方式进行命名。 例如,AppDomain 有一个称为 SetCachePath
的方法,而不是一个仅设置属性名为 CachePath
的属性。
✔️ 请为所有属性提供合理的默认值,确保默认值不会导致安全漏洞或非常低效的代码。
✔️ DO 允许按任意顺序设置属性,即使这会导致对象的临时无效状态。
同一对象上的两个或多个属性通常会相互关联,以至于某个属性的某些值在考虑其他属性的值时可能无效。 在这种情况下,由于无效状态导致的异常应推迟到对象实际使用相关属性为止。
✔️ 如果属性 setter 引发异常,请保留以前的值。
❌ 避免在属性读取器中引发异常。
属性访问器应该是简单的操作,不应有任何前置条件。 如果 getter 可以引发异常,它应该重新设计为方法。 请注意,此规则不适用于索引器,在索引器中,我们期望异常作为验证参数的结果。
索引属性设计
索引属性是一个具有参数的特殊属性,可以使用类似于数组索引的特殊语法调用。
索引属性通常称为索引器。 索引器应仅在提供对逻辑集合中的项的访问权限的 API 中使用。 例如,字符串是字符集合,添加了索引器 System.String 以访问其字符。
✔️ 请考虑使用索引器提供对内部数组中存储的数据的访问权限。
✔️ 请考虑为表示项集合的类型提供索引器。
❌ 避免对多个参数使用索引属性。
如果设计需要多个参数,请重新考虑该属性是否真的表示逻辑集合的访问器。 如果不是,请使用其他方法。 请考虑使用Get
或Set
作为方法名称的开头。
❌避免使用参数类型是System.Int32、System.Int64、System.String、System.Object或枚举以外的索引器。
如果设计需要其他类型的参数,请强烈重新评估 API 是否真的表示逻辑集合的访问器。 如果没有,请使用一种方法。 请考虑使用Get
或Set
作为方法名称的开头。
✔️ 请对索引属性使用 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 公司。 保留所有权利。