Разработка свойствProperty Design

Хотя свойства технически похожи на методы, они сильно отличаются в плане их сценариев использования.Although properties are technically very similar to methods, they are quite different in terms of their usage scenarios. Они должны отображаться как интеллектуальные поля.They should be seen as smart fields. Они имеют синтаксис для вызова полей и гибкость методов.They have the calling syntax of fields, and the flexibility of methods.

✔️ создать свойства только для получения, если вызывающий объект не может изменить значение свойства.✔️ DO create get-only properties if the caller should not be able to change the value of the property.

Помните, что если тип свойства является изменяемым ссылочным типом, значение свойства можно изменить, даже если это свойство доступно только для получения.Keep in mind that if the type of the property is a mutable reference type, the property value can be changed even if the property is get-only.

❌ не предоставляют свойства или свойства только для установки с методом задания, имеющим более широкие возможности доступа, чем метод получения.❌ DO NOT provide set-only properties or properties with the setter having broader accessibility than the getter.

Например, не используйте свойства с открытым методом задания и защищенным методом считывания.For example, do not use properties with a public setter and a protected getter.

Если метод получения свойства не может быть предоставлен, реализуйте в качестве метода функцию.If the property getter cannot be provided, implement the functionality as a method instead. Рассмотрите возможность запуска имени метода с Set и выполните действия с именем свойства.Consider starting the method name with Set and follow with what you would have named the property. Например, AppDomain имеет метод с именем SetCachePath вместо того, чтобы иметь свойство только для набора, именуемое CachePath.For example, AppDomain has a method called SetCachePath instead of having a set-only property called CachePath.

✔️ предоставляют разумные значения по умолчанию для всех свойств, гарантируя, что значения по умолчанию не приводят к появлению бреши в системе безопасности или неэффективному коду.✔️ DO provide sensible default values for all properties, ensuring that the defaults do not result in a security hole or terribly inefficient code.

✔️ разрешить задавать свойства в любом порядке, даже если это приводит к временному недопустимому состоянию объекта.✔️ DO allow properties to be set in any order even if this results in a temporary invalid state of the object.

Обычно два или более свойства взаимосвязаны с точкой, в которой некоторые значения одного свойства могут быть недопустимыми с учетом значений других свойств одного и того же объекта.It is common for two or more properties to be interrelated to a point where some values of one property might be invalid given the values of other properties on the same object. В таких случаях исключения, являющиеся результатом недопустимого состояния, должны быть отложены до тех пор, пока взаимосвязанные свойства фактически не будут использоваться объектом вместе.In such cases, exceptions resulting from the invalid state should be postponed until the interrelated properties are actually used together by the object.

✔️ сохранить предыдущее значение, если метод задания свойства создает исключение.✔️ DO preserve the previous value if a property setter throws an exception.

❌ избежать возникновения исключений из методов получения свойств.❌ AVOID throwing exceptions from property getters.

Методы получения свойств должны быть простыми операциями и не должны иметь никаких предусловий.Property getters should be simple operations and should not have any preconditions. Если метод получения может вызвать исключение, то, возможно, он будет переработано, чтобы быть методом.If a getter can throw an exception, it should probably be redesigned to be a method. Обратите внимание, что это правило не применяется к индексаторам, в которых мы предполагаем исключения в результате проверки аргументов.Notice that this rule does not apply to indexers, where we do expect exceptions as a result of validating the arguments.

Разработка индексированных свойствIndexed Property Design

Индексированное свойство — это специальное свойство, которое может иметь параметры и может вызываться с помощью специального синтаксиса, аналогичного индексированию массива.An indexed property is a special property that can have parameters and can be called with special syntax similar to array indexing.

Индексированные свойства обычно называются индексаторами.Indexed properties are commonly referred to as indexers. Индексаторы следует использовать только в интерфейсах API, которые предоставляют доступ к элементам в логической коллекции.Indexers should be used only in APIs that provide access to items in a logical collection. Например, строка представляет собой набор символов, а индексатор для System.String был добавлен для доступа к его символам.For example, a string is a collection of characters, and the indexer on System.String was added to access its characters.

✔️ Рассмотрите возможность использования индексаторов для предоставления доступа к данным, хранящимся во внутреннем массиве.✔️ CONSIDER using indexers to provide access to data stored in an internal array.

✔️ Рассмотрите возможность предоставления индексаторов для типов, представляющих коллекции элементов.✔️ CONSIDER providing indexers on types representing collections of items.

❌ Избегайте использования индексированных свойств более чем с одним параметром.❌ AVOID using indexed properties with more than one parameter.

Если для проектирования требуется несколько параметров, следует подумать, действительно ли свойство представляет метод доступа к логической коллекции.If the design requires multiple parameters, reconsider whether the property really represents an accessor to a logical collection. Если это не так, используйте вместо них методы.If it does not, use methods instead. Попробуйте запустить имя метода с помощью Get или Set.Consider starting the method name with Get or Set.

❌ избегать использования индексаторов с типами параметров, отличными от System.Int32, System.Int64, System.String, System.Objectили перечисления.❌ AVOID indexers with parameter types other than System.Int32, System.Int64, System.String, System.Object, or an enum.

Если для разработки требуются другие типы параметров, настоятельно повторно оцените, действительно ли API представляет метод доступа к логической коллекции.If the design requires other types of parameters, strongly reevaluate whether the API really represents an accessor to a logical collection. В противном случае используйте метод.If it does not, use a method. Попробуйте запустить имя метода с помощью Get или Set.Consider starting the method name with Get or Set.

✔️ использовать имя Item для индексированных свойств, если нет очевидного лучшего имени (например, см. свойство Chars[Int32] в System.String).✔️ DO use the name Item for indexed properties unless there is an obviously better name (e.g., see the Chars[Int32] property on System.String).

В C#индексаторы по умолчанию имеют именованный элемент.In C#, indexers are by default named Item. Для настройки этого имени можно использовать IndexerNameAttribute.The IndexerNameAttribute can be used to customize this name.

❌ не предоставляют и индексатор, и методы, которые являются семантически эквивалентными.❌ DO NOT provide both an indexer and methods that are semantically equivalent.

❌ не предоставляют более одного семейства перегруженных индексаторов в одном типе.❌ DO NOT provide more than one family of overloaded indexers in one type.

Это обеспечивается C# компилятором.This is enforced by the C# compiler.

❌ не используют индексированные свойства, не являющиеся свойствами по умолчанию.❌ DO NOT use nondefault indexed properties.

Это обеспечивается C# компилятором.This is enforced by the C# compiler.

События уведомления об изменении свойствProperty Change Notification Events

Иногда бывает полезно указать событие, уведомляющее пользователя об изменениях в значении свойства.Sometimes it is useful to provide an event notifying the user of changes in a property value. Например, System.Windows.Forms.Control вызывает событие TextChanged после изменения значения свойства Text.For example, System.Windows.Forms.Control raises a TextChanged event after the value of its Text property has changed.

✔️ Рассмотрите возможность вызова событий уведомлений об изменениях при изменении значений свойств в интерфейсах API высокого уровня (обычно в компонентах конструктора).✔️ CONSIDER raising change notification events when property values in high-level APIs (usually designer components) are modified.

Если есть хороший сценарий, при котором пользователю известно, когда изменяется свойство объекта, объект должен создать событие уведомления об изменении для свойства.If there is a good scenario for a user to know when a property of an object is changing, the object should raise a change notification event for the property.

Однако вряд ли стоит тратить издержки на создание таких событий для низкоуровневых API, таких как базовые типы или коллекции.However, it is unlikely to be worth the overhead to raise such events for low-level APIs such as base types or collections. Например, List<T> не будет вызывать такие события при добавлении нового элемента в список и изменении свойства Count.For example, List<T> would not raise such events when a new item is added to the list and the Count property changes.

✔️ Рассмотрите возможность создания событий уведомления об изменениях, когда значение свойства изменяется через внешние силы.✔️ CONSIDER raising change notification events when the value of a property changes via external forces.

Если значение свойства изменяется с помощью некоторой внешней силы (не путем вызова методов объекта), события вызываются разработчиком, что значение изменяется и изменилось.If a property value changes via some external force (in a way other than by calling methods on the object), raise events indicate to the developer that the value is changing and has changed. Хорошим примером является свойство Text элемента управления "текстовое поле".A good example is the Text property of a text box control. Когда пользователь вводит текст в TextBox, значение свойства изменяется автоматически.When the user types text in a TextBox, the property value automatically changes.

Части © 2005, 2009 Корпорация Майкрософт. Все права защищены.Portions © 2005, 2009 Microsoft Corporation. All rights reserved.

Перепечатано с разрешения Pearson Education, Inc. из книги Инфраструктура программных проектов. Соглашения, идиомы и шаблоны для многократно используемых библиотек .NET (2-е издание), авторы: Кржиштоф Цвалина (Krzysztof Cwalina) и Брэд Абрамс (Brad Abrams). Книга опубликована 22 октября 2008 г. издательством Addison-Wesley Professional в рамках серии, посвященной разработке для Microsoft Windows.Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, published Oct 22, 2008 by Addison-Wesley Professional as part of the Microsoft Windows Development Series.

См. также разделSee also