Эта стратегия предполагает замену подобных:
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; }
}
С:
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;
}
}
Почему именно это предпочтительнее, чем делать тип перечислением, например так:
public class Politician
{
public MostNotableGrievance MostNotableGrievance { get; set; }
}
public enum MostNotableGrievance
{
Infidelity = 0,
Embezzlement = 1,
FlipFlopping = 2,
Murder = 3,
BabyKissing = 4
}
С типом не связано поведение, и если бы это было, вы бы в любом случае использовали рефакторинг другого типа, например, «Заменить код типа на подклассы» + «Заменить условный на полиморфизм».
Тем не менее, автор объясняет, почему он не одобряет этот метод (на Java?):
Числовые коды типов или перечисления являются общей чертой языков Си. С символическими именами они могут быть вполне читабельными. Проблема в том, что символическое имя является только псевдонимом; Компилятор по-прежнему видит основной номер. Тип компилятора проверяет номер 177, а не символическое имя. Любой метод, который принимает код типа в качестве аргумента, ожидает число, и нет ничего, чтобы принудительно использовать символическое имя. Это может снизить читабельность и стать источником ошибок.
Но при попытке применить этот оператор к C # этот оператор не выглядит верным: он не будет принимать число, потому что перечисление фактически считается классом. Итак, следующий код:
public class Test
{
public void Do()
{
var temp = new Politician { MostNotableGrievance = 1 };
}
}
Не будет компилироваться. Так можно ли считать этот рефакторинг ненужным в новых языках высокого уровня, таких как C #, или я что-то не рассматриваю?
источник
var temp = new Politician { MostNotableGrievance = MostNotableGrievance.Embezzlement };
Ответы:
Я думаю, что вы почти ответили на свой вопрос там.
Второй кусок кода предпочтительнее первого, потому что он обеспечивает безопасность типов. В первой части, если у вас есть аналогичное перечисление рыбы, вы можете сказать что-то вроде
и компилятору все равно. Если Fish.Haddock = 2, то приведенное выше будет в точности эквивалентно
но, очевидно, не сразу читается как таковой.
Причины перечисления часто не лучше, потому что неявное преобразование в и из int оставляет вас с той же самой проблемой.
Но в C # такого неявного преобразования нет, поэтому enum - лучшая структура для использования. Вы редко увидите один из первых двух подходов.
источник
Если с этим значением нет поведения, и нет никакой дополнительной информации, которую нужно хранить рядом с ним, а язык не поддерживает неявное преобразование в целые числа, я бы использовал enum; вот для чего они здесь.
источник
Другой пример, который может вам помочь, можно найти в Effective Java (пункт 30, если вы хотите посмотреть его). Это верно и для C #.
Предположим, вы используете int-константы для моделирования различных животных, например, змей и собак.
Предположим, что они являются константами и, возможно, даже определены в разных классах. Это может показаться вам хорошим, и это может сработать. Но рассмотрим эту строку кода:
Понятно, что это ошибка. Компилятор не будет жаловаться, и код будет выполнен. Но твоя змея не превратится в собаку. Это потому, что компилятор видит только:
Ваша змея на самом деле питон (а не терьер). Эта функция называется безопасностью типов и фактически является причиной того, почему вы используете пример кода.
не скомпилируется. MostNotableGrievance - это MostNotableGrievance, а не целое число. С помощью перечислений вы можете выразить это в системе типов. И именно поэтому мы с Мартином Фаулером считаем, что перечисления великолепны.
источник