День двести двадцать девятый. #BestPractices
Советы по разработке членов типов
Перегрузка операторов
Перегрузки операторов позволяют типам фреймворка выглядеть так, как если бы они были встроенными примитивными типами. Хотя в некоторых ситуациях это допустимо и полезно, их следует использовать с осторожностью. Существует много случаев злоупотребления, например, когда разработчики использовали перегрузку операторов для операций, которые должны быть простыми методами.
⚠️ РАССМОТРИТЕ определение перегрузки операторов в типе, который должен выглядеть как примитивный тип. Например, для
❌ ИЗБЕГАЙТЕ определения перегрузок операторов, за исключением типов, которые должны выглядеть как примитивные (встроенные) типы.
✅ ИСПОЛЬЗУЙТЕ перегрузки операторов в структурах, которые представляют числа (например,
✅ ИСПОЛЬЗУЙТЕ перегрузки операторов только в тех случаях, когда очевидно, каким будет результат операции. Например, имеет смысл вычесть один
❌ ИЗБЕГАЙТЕ перегрузки оператора, если хотя бы один из операндов не относится к типу, определяющему перегрузку.
✅ ИСПОЛЬЗУЙТЕ симметричную перегрузку операторов. Например, если вы перегружаете оператор
⚠️ РАССМОТРИТЕ предоставление методов с понятными именами, которые соответствуют каждому перегруженному оператору. Многие языки не поддерживают перегрузку операторов. По этой причине рекомендуется, чтобы типы, которые перегружали операторы, включали вторичный метод с соответствующим именем, обеспечивающим эквивалентную функциональность, например,
Перегрузка оператора
Операторы преобразования
Операторы преобразования - это унарные операторы, которые допускают преобразование из одного типа в другой. Операторы должны быть определены как статические члены либо для операнда, либо для типа возвращаемого значения. Существует два типа операторов преобразования: неявные и явные.
❌ ИЗБЕГАЙТЕ предоставления оператора преобразования, если конечные пользователи не ожидают такого преобразования.
❌ ИЗБЕГАЙТЕ определения оператора преобразования вне домена типа. Например,
❌ ИЗБЕГАЙТЕ предоставления оператора неявного преобразования, если преобразование потенциально приводит к потерям. Например, не должно быть неявного преобразования из
❌ ИЗБЕГАЙТЕ выброса исключений из неявных преобразований. Конечным пользователям очень трудно понять, что происходит, потому что они могут не знать, что происходит преобразование.
✅ ИСПОЛЬЗУЙТЕ выброс
Продолжение следует…
Источник: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/
Советы по разработке членов типов
Перегрузка операторов
Перегрузки операторов позволяют типам фреймворка выглядеть так, как если бы они были встроенными примитивными типами. Хотя в некоторых ситуациях это допустимо и полезно, их следует использовать с осторожностью. Существует много случаев злоупотребления, например, когда разработчики использовали перегрузку операторов для операций, которые должны быть простыми методами.
⚠️ РАССМОТРИТЕ определение перегрузки операторов в типе, который должен выглядеть как примитивный тип. Например, для
System.String
определены операторы ==
и !=
.❌ ИЗБЕГАЙТЕ определения перегрузок операторов, за исключением типов, которые должны выглядеть как примитивные (встроенные) типы.
✅ ИСПОЛЬЗУЙТЕ перегрузки операторов в структурах, которые представляют числа (например,
System.Decimal
).✅ ИСПОЛЬЗУЙТЕ перегрузки операторов только в тех случаях, когда очевидно, каким будет результат операции. Например, имеет смысл вычесть один
DateTime
из другого DateTime
и получить TimeSpan
. Однако нецелесообразно использовать оператор логического объединения для объединения двух запросов к базе данных или использовать оператор сдвига для записи в поток.❌ ИЗБЕГАЙТЕ перегрузки оператора, если хотя бы один из операндов не относится к типу, определяющему перегрузку.
✅ ИСПОЛЬЗУЙТЕ симметричную перегрузку операторов. Например, если вы перегружаете оператор
==
, вам также следует перегрузить оператор !=
. Точно так же, если вы перегружаете оператор <
, вы также должны перегружать оператор >
и так далее.⚠️ РАССМОТРИТЕ предоставление методов с понятными именами, которые соответствуют каждому перегруженному оператору. Многие языки не поддерживают перегрузку операторов. По этой причине рекомендуется, чтобы типы, которые перегружали операторы, включали вторичный метод с соответствующим именем, обеспечивающим эквивалентную функциональность, например,
+
- Add
, ==
- Equals
, ++
- Increment
, &
- BitwiseAnd
и т.п.Перегрузка оператора
==
довольно сложна. Семантика оператора должна быть совместима с несколькими другими членами, такими как Object.Equals
.Операторы преобразования
Операторы преобразования - это унарные операторы, которые допускают преобразование из одного типа в другой. Операторы должны быть определены как статические члены либо для операнда, либо для типа возвращаемого значения. Существует два типа операторов преобразования: неявные и явные.
❌ ИЗБЕГАЙТЕ предоставления оператора преобразования, если конечные пользователи не ожидают такого преобразования.
❌ ИЗБЕГАЙТЕ определения оператора преобразования вне домена типа. Например,
Int32
, Double
и Decimal
являются числовыми типами, а DateTime
- нет. Следовательно, не должно быть оператора преобразования для преобразования Double (long)
в DateTime
. В таком случае более предпочтительным является конструктор.❌ ИЗБЕГАЙТЕ предоставления оператора неявного преобразования, если преобразование потенциально приводит к потерям. Например, не должно быть неявного преобразования из
Double
в Int32
, потому что Double
имеет более широкий диапазон, чем Int32
. Явный оператор преобразования может быть предоставлен, даже если преобразование потенциально связано с потерями.❌ ИЗБЕГАЙТЕ выброса исключений из неявных преобразований. Конечным пользователям очень трудно понять, что происходит, потому что они могут не знать, что происходит преобразование.
✅ ИСПОЛЬЗУЙТЕ выброс
System.InvalidCastException
, если вызов оператора приведения приводит к конвертации с потерями, а контракт оператора не допускает конвертации с потерями.Продолжение следует…
Источник: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/