属性设计
通常,方法代表操作而属性代表数据。属性像字段一样使用,这意味着属性不应进行复杂的计算,也不应产生副作用。有关属性设计的更多信息,请参见索引属性设计和属性更改通知事件。
下列准则可帮助确保正确地设计属性。 如果调用方不应当更改属性值,则要创建只读属性。
注意,属性类型的可变性会影响最终用户可以更改的内容。例如,如果定义一个返回读/写集合的只读属性,则最终用户不能向该属性分配其他集合,但可以修改该集合中的元素。 不要提供仅支持 Set 操作的属性。
如果无法提供属性 getter,可以改用一个方法来实现该功能。方法名称应以 Set 开头,并按原样后跟属性名。例如,AppDomain 使用一个名为 SetCachePath 的方法,而不是名为 CachePath 的仅支持 Set 操作的属性。 为所有属性提供适当的默认值,确保属性的默认值不会导致安全漏洞或设计效率非常低下。 允许按任意顺序设置属性,即便这样做会导致出现暂时无效的对象状态也如此。 如果属性 setter 引发异常,则保留以前的值。 避免从属性 getter 中引发异常。
属性 getter 应是没有任何前提条件的简单操作。如果 getter 可能会引发异常,请考虑将该属性重新设计为方法。此项建议不适用于索引器。索引可以因参数无效而引发异常。
在属性 setter 中引发异常是有效并可以接受的。
属性更改通知事件
属性更改通知事件用于在属性值因内部或外部活动发生更改时向代码发出通知。这使得代码可以根据需要更新相关状态(例如,改变用户界面中控件的外观)。 当修改高级 API(通常是设计器组件)中的属性值时,应考虑引发更改通知事件。
这项准则适用于那些可通过更改通知将重要值添加到库的高级成员。例如,提供用户界面或与之交互的对象使用更改通知使相关用户界面对象相应地得到更新。当不向库添加值或通知会频繁地执行以致对性能造成严重影响的情况下,不应使用更改通知事件。例如,在每次向常规集合添加元素或将元素从中删除时就引发更改通知事件是不正确的。若要避免给常用类型增加不必要的复杂性,在需要这一功能时应使用一个专用集合。.NET Framework 2.0 版的库提供了 Collection,该集合用作常规集合。Framework 还为需要通知的集合提供了 BindingList。 当属性值由于外部因素发生更改时,应考虑引发更改通知事件。
如果属性值由于某种外部因素(如用户输出)发生更改,则应在更改永久生效之前使用更改通知事件指示该值即将更改。在更改永久生效后,可使用另一事件指示该值已进行了更改。例如,Control 类提供了 Validating 和 Validated 事件来向代码发出验证控件的通知
索引属性设计
索引属性允许像访问数组一样对一组项(例如字符串中的字符,或 BitArray 中的位)进行访问。索引属性(称为索引器或默认属性)与常规属性不同,因为索引属性接受参数,参数指示要访问组中的哪个元素。索引属性的实现应尽可能简单,因为索引器经常在循环中使用。下面的准则帮助确保您的类型在适当情况下包含设计良好的索引。 考虑使用索引器提供对存储在内部数组中的数据的访问。 考虑对表示项的集合的类型提供索引器。 避免使用具有多个参数的索引属性。
如果一个索引器需要多个参数,请重新评估该属性是否确实表示对逻辑集合的访问。如果不是,则改用方法,并考虑选择以 Get 或 Set 开头的方法名。避免为索引器设置除 System.Int32、System.Int64、System.String、System.Object、枚举或泛型类型参数之外的其他参数类型。
如果设计需要其他类型的参数,应该仔细重新评估该成员是否确实表示对逻辑集合的访问。如果不是,则改用方法,并考虑选择以 Get 或 Set 开头的方法名。 将“Item”名称用于索引属性,除非明显有更好的名称(有关示例,请参见 System.String.Chars(System.Int32) 属性)。
使用 IndexerNameAttribute 属性可自定义索引器的名称。 不要同时提供在语义上等效的索引器和方法。
在下面的代码示例中,索引器应改为方法。
Visual Basic
1<System.Runtime.CompilerServices.IndexerNameAttribute("PositionsHeld")> _
2Public Property Item()Property Item (skillId as Integer) as JobInfoCollection
3 Public Function GetPositions()Function GetPositions(skillId as Integer, _
4minJobLevel as Integer) _
5as JobInfoCollection
6
C#
不要在一个类型中提供一组以上的重载索引器。1[System.Runtime.CompilerServices.IndexerNameAttribute("PositionsHeld")]
2public JobInfoCollection this [int skillId]
3 public JobInfoCollection GetPositions(int skillId, int minJobLevel)
4
一些编译器(如 C# 编译器)会强制实施此准则。
有些语言不支持多组索引器。如果使用了多组索引器,有些开发人员将无法访问这些成员。 不要使用非默认索引属性。
一些编译器(如 C# 编译器)会强制实施此准则。并不是所有编程语言都支持非默认索引属性。如果使用了非默认索引属性,有些开发人员将无法访问这些成员。