День двести двадцать девятый. #BestPractices

Советы по разработке членов типов

Перегрузка операторов

Перегрузки операторов позволяют типам фреймворка выглядеть так, как если бы они были встроенными примитивными типами. Хотя в некоторых ситуациях это допустимо и полезно, их следует использовать с осторожностью. Существует много случаев злоупотребления, например, когда разработчики использовали перегрузку операторов для операций, которые должны быть простыми методами.



⚠️ РАССМОТРИТЕ определение перегрузки операторов в типе, который должен выглядеть как примитивный тип. Например, для 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/