В C # мы можем перегрузить оператор неявного преобразования следующим образом (пример из MSDN ):
struct Digit
{
/* ... */
public static implicit operator byte(Digit d) // implicit digit to byte conversion operator
{
/* ... */
}
}
Таким образом, мы можем иметь тип, пользовательский тип значения , магически преобразующий себя в другой (не связанный) тип, оставляя аудиторию в недоумении (пока они не заглянут в кулисы и не увидят оператор неявного преобразования, то есть).
Я не люблю оставлять кого-то, кто читает мой код в недоумении. Я не думаю, что многие люди делают.
Вопрос в том, каковы варианты использования оператора неявного преобразования типов, которые не сделают мой код более трудным для понимания?
Ответы:
Я бы рекомендовал неявные преобразования между типами, которые по-разному представляют одни и те же значения. Например:
RGB
,HSL
,HSV
иCMYK
.Meter
противInch
).Тем не менее, есть некоторые сильные рекомендации , которые указывают , когда оно не уместно определить неявное преобразование:
InvalidCast
вызвать исключение ( ), то оно не должно быть неявным.O(1)
операцией, то оно не должно быть неявным.Теперь предположим, что ваш оператор преобразования
f: T1 -> T2
не нарушает ни одно из вышеприведенных правил, тогда следующее поведение убедительно показывает, что преобразование может быть неявным:a == b
тогдаf(a) == f(b)
.a != b
тогдаf(a) != f(b)
.a.ToString() == b.ToString()
тогдаf(a).ToString() == f(b).ToString()
.T1
иT2
.источник
T1
(подразумеваемом==
отношением onT1
) всегда отображаются на два значения в одном и том же классе эквивалентностиT2
. Теперь, когда я думаю об этом, я предполагаю, что первое свойство на самом деле должно требоваться для неявного преобразования.Когда типы не связаны (с программистами). Есть (редкие) сценарии, когда у вас есть два не связанных типа (с точки зрения кода), которые на самом деле связаны (с точки зрения предметной области или разумных программистов).
Например, некоторый код для сопоставления строк. Обычный сценарий - сопоставление строкового литерала. Вместо вызова
IsMatch(input, new Literal("some string"))
неявное преобразование позволяет вам избавиться от этой церемонии - шума в коде - и сосредоточиться на строковом литерале.Большинство программистов увидят
IsMatch(input, "some string")
и быстро поймут, что происходит. Это делает ваш код более понятным на сайте вызова. Короче говоря, это немного облегчает понимание того, что происходит, за небольшую цену того, как это происходит.Теперь вы можете утверждать, что простая перегрузка функции для выполнения того же действия была бы лучше. И это. Но если такого рода вещи встречаются повсеместно, то одно преобразование будет чище (меньше кода, повышенная согласованность), чем выполнение множества перегрузок функций.
И вы можете возразить, что лучше потребовать от программистов явного создания промежуточного типа, чтобы они видели «что на самом деле происходит». Это не так просто. Лично я думаю, что пример буквального совпадения строк очень ясно говорит о «что происходит на самом деле» - программисту не нужно знать механизм того, как все происходит. Знаете ли вы, как весь ваш код выполняется различными процессорами, на которых он работает? Всегда есть линия абстракции, где программисты перестают заботиться о том, как что-то работает. Если вы считаете, что шаги неявного преобразования важны, не используйте неявное преобразование. Если вы думаете, что это просто церемония, чтобы сохранить компьютер счастливым, и программисту было бы лучше не видеть этот шум повсюду,
источник