Essa estratégia envolve a substituição de coisas como essa:
public class Politician
{
public const int Infidelity = 0;
public const int Embezzlement = 1;
public const int FlipFlopping = 2;
public const int Murder = 3;
public const int BabyKissing = 4;
public int MostNotableGrievance { get; set; }
}
Com:
public class Politician
{
public MostNotableGrievance MostNotableGrievance { get; set; }
}
public class MostNotableGrievance
{
public static readonly MostNotableGrievance Infidelity = new MostNotableGrievance(0);
public static readonly MostNotableGrievance Embezzlement = new MostNotableGrievance(1);
public static readonly MostNotableGrievance FlipFlopping = new MostNotableGrievance(2);
public static readonly MostNotableGrievance Murder = new MostNotableGrievance(3);
public static readonly MostNotableGrievance BabyKissing = new MostNotableGrievance(4);
public int Code { get; private set; }
private MostNotableGrievance(int code)
{
Code = code;
}
}
Por que exatamente isso é preferível a tornar o tipo uma enumeração, assim:
public class Politician
{
public MostNotableGrievance MostNotableGrievance { get; set; }
}
public enum MostNotableGrievance
{
Infidelity = 0,
Embezzlement = 1,
FlipFlopping = 2,
Murder = 3,
BabyKissing = 4
}
Não há comportamento associado ao tipo e, se houver, você usaria um tipo diferente de refatoração de qualquer maneira, por exemplo, 'Substituir código de tipo por subclasses' + 'Substituir condicional por polimorfismo'.
No entanto, o autor explica por que ele desaprova esse método (em Java?):
Códigos de tipo numérico, ou enumerações, são um recurso comum de linguagens baseadas em C. Com nomes simbólicos, eles podem ser bastante legíveis. O problema é que o nome simbólico é apenas um apelido; o compilador ainda vê o número subjacente. O tipo de compilador verifica usando o número 177 e não o nome simbólico. Qualquer método que usa o código de tipo como argumento espera um número e não há nada para forçar o uso de um nome simbólico. Isso pode reduzir a legibilidade e ser uma fonte de bugs.
Mas, ao tentar aplicar esta declaração ao C #, essa declaração não parece verdadeira: ela não aceita um número porque uma enumeração é realmente considerada uma classe. Portanto, o seguinte código:
public class Test
{
public void Do()
{
var temp = new Politician { MostNotableGrievance = 1 };
}
}
Não será compilado. Portanto, essa refatoração pode ser considerada desnecessária em linguagens de alto nível mais recentes, como C #, ou não estou pensando em algo?
fonte
var temp = new Politician { MostNotableGrievance = MostNotableGrievance.Embezzlement };
Respostas:
Eu acho que você quase respondeu sua própria pergunta lá.
O segundo trecho de código é preferível ao primeiro porque oferece segurança de tipo. Com a primeira peça, se você tiver uma enumeração semelhante de Fish, poderá dizer algo como
e o compilador não se importa. Se Fish.Haddock = 2, o acima será exatamente equivalente a
mas obviamente não é instantaneamente legível como tal.
A razão pela qual as enumerações geralmente não são melhores é porque a conversão implícita de e para int deixa você exatamente com o mesmo problema.
Mas, em C #, não existe essa conversão implícita; portanto, um enum é uma estrutura melhor para usar. Você raramente verá uma das duas primeiras abordagens usadas.
fonte
Se não houver comportamento associado ao valor e não houver informações extras que você precise armazenar ao lado dele e o idioma não suportar conversão implícita em números inteiros, eu usaria uma enumeração; é para isso que eles estão lá.
fonte
Outro exemplo que pode ajudá-lo pode ser encontrado em Java Efetivo (item 30, se você quiser procurá-lo). Também é válido para C #.
Suponha que você use constantes int para modelar animais diferentes, como cobras e cães.
Suponha que sejam constantes e talvez até definidas em diferentes classes. Isso pode parecer bom para você e pode realmente funcionar. Mas considere esta linha de código:
Claramente, isso é um erro. O compilador não irá reclamar e o código será executado. Mas sua cobra não vai se transformar em um cachorro. Isso ocorre porque o compilador vê apenas:
Sua cobra é na verdade um python (e não um terrier). Esse recurso é chamado de segurança de tipo e é realmente a razão pela qual você é um exemplo de código
não irá compilar. MostNotableGrievance é MostNotableGrievance e não um número inteiro. Com enums, você pode expressar isso no sistema de tipos. E é por isso que Martin Fowler e eu pensamos que as enumerações são ótimas.
fonte