Em C #, podemos sobrecarregar o operador de conversão implícita como este (exemplo do MSDN ):
struct Digit
{
/* ... */
public static implicit operator byte(Digit d) // implicit digit to byte conversion operator
{
/* ... */
}
}
Assim, podemos ter um tipo, um tipo de valor personalizado , convertendo-se magicamente para outro tipo (não relacionado), deixando a platéia perplexa (até que eles olhem nos bastidores e vejam o operador implícito de conversão).
Não gosto de deixar ninguém que leia meu código com perplexidade. Eu não acho que muitas pessoas fazem.
A questão é: quais são os casos de uso do operador implícito de conversão de tipo que não tornarão meu código muito mais difícil de entender?
Respostas:
Eu recomendaria apenas conversões implícitas entre tipos que representam aproximadamente os mesmos valores de maneiras diferentes. Por exemplo:
RGB
,HSL
,HSV
eCMYK
.Meter
vsInch
).No entanto, existem algumas orientações fortes que indicam quando é não adequado definir uma conversão implícita:
InvalidCast
exceção ( ), não deverá estar implícita.O(1)
operação, ela não deverá estar implícita.Agora, digamos que seu operador de conversão
f: T1 -> T2
não viole nenhuma das regras acima, o comportamento a seguir indica fortemente que a conversão pode estar implícita:a == b
entãof(a) == f(b)
.a != b
entãof(a) != f(b)
.a.ToString() == b.ToString()
entãof(a).ToString() == f(b).ToString()
.T1
eT2
.fonte
T1
(implícita na==
relação onT1
) sempre são mapeados para dois valores na mesma classe de equivalência deT2
. Agora que penso nisso, acho que a primeira propriedade deve ser realmente necessária para uma conversão implícita.Quando os tipos não estão relacionados (para programadores). Existem cenários (raros) em que você tem dois tipos não relacionados (no que diz respeito ao código), que são realmente relacionados (no que diz respeito ao domínio ou programadores razoáveis).
Por exemplo, algum código para fazer a correspondência de cadeias. Um cenário comum é corresponder a uma string literal. Em vez de chamar
IsMatch(input, new Literal("some string"))
, uma conversão implícita permite que você se livre dessa cerimônia - o barulho no código - e concentre-se na cadeia de caracteres literal.A maioria dos programadores verá
IsMatch(input, "some string")
e intuirá rapidamente o que está acontecendo. Isso torna seu código mais claro no site da chamada. Em resumo, torna um pouco mais fácil entender o que está acontecendo, com uma pequena despesa de como isso está acontecendo.Agora, você pode argumentar que uma sobrecarga de função simples para fazer a mesma coisa seria melhor. E isso é. Mas se esse tipo de coisa é onipresente, ter uma conversão é mais limpo (menos código, maior consistência) do que fazer uma pilha de sobrecargas de funções.
E você pode argumentar que é melhor exigir que os programadores criem explicitamente o tipo intermediário para que vejam "o que realmente está acontecendo". Isso é menos direto. Pessoalmente, acho que o exemplo literal de correspondência de strings é muito claro sobre "o que realmente está acontecendo" - o programador não precisa conhecer a mecânica de como tudo acontece. Você sabe como todo o seu código é executado pelos vários processadores em que o código é executado? Sempre há uma linha de abstração em que os programadores param de se preocupar com o funcionamento de algo. Se você acha que as etapas implícitas de conversão são importantes, não use a conversão implícita. Se você acha que eles são apenas uma cerimônia para manter o computador feliz, e o programador seria melhor não ver esse barulho em todos os lugares,
fonte