Стандарты кодирования C # Лэнса Ханта - PullRequest
15 голосов
/ 27 февраля 2009

Моя команда недавно начала использовать документ Стандарты кодирования C # Lance Hunt в качестве отправной точки для консолидации наших стандартов кодирования.

Есть одна вещь, которую мы просто не понимаем, может кто-нибудь здесь пролить свет на это?

Артикул № 77:

Всегда проверять перечисление значение переменной или параметра перед потребляя это. Они могут содержать любые значение, которое лежит в основе типа Enum (по умолчанию int) поддерживает.

Пример:

public void Test(BookCategory cat)
{
if (Enum.IsDefined(typeof(BookCategory), cat))
{…}
}

Ответы [ 5 ]

20 голосов
/ 27 февраля 2009

Дело в том, что вы можете надеяться, что, имея параметр типа BookCategory, у вас всегда будет значимая категория книги. Это не тот случай. Я мог бы позвонить:

BookCategory weirdCategory = (BookCategory) 123456;
Test(weirdCategory);

Если перечисление предназначено для представления общеизвестного набора значений, не следует ожидать, что код будет разумно обрабатывать значение за пределами этого общеизвестного набора. Тест проверяет, подходит ли аргумент первым.

Я бы лично изменил логику, хотя:

public void Test(BookCategory cat)
{
    if (!Enum.IsDefined(typeof(BookCategory), cat))
    {
        throw new ArgumentOutOfRangeException("cat");
    }
}

В C # 3 это легко сделать с помощью метода расширения:

// Can't constrain T to be an enum, unfortunately. This will have to do :)
public static void ThrowIfNotDefined<T>(this T value, string name) where T : struct
{
    if (!Enum.IsDefined(typeof(T), value))
    {
        throw new ArgumentOutOfRangeException(name);
    }
}

Использование:

public void Test(BookCategory cat)
{
    cat.ThrowIfNotDefined("cat");
}
17 голосов
/ 27 февраля 2009

Перечни не проверяются:

enum Foo { A= 1, B = 2, C = 3}
Foo x = (Foo) 27; // works fine

Теперь у вас есть Foo, который не определен. Он просто говорит «проверь свой вклад». Обратите внимание, что Enum.IsDefined относительно медленно (на основе отражения). Лично я склонен использовать переключатель с default, который выдает исключение:

switch(x) {
    case Foo.A: /* do something */ break;
    case Foo.B: /* do something */ break;
    case Foo.C: /* do something */ break;
    default: throw new ArgumentOutOfRangeException("x");
}
13 голосов
/ 27 февраля 2009

Я думаю, что комментарии выше в значительной степени ответили на вопрос. По сути, когда я писал это правило, я пытался передать защитную практику кодирования для проверки всех входных данных. Перечисления являются особым случаем, потому что многие разработчики ошибочно полагают, что они проверены, а они нет. В результате вы часто будете видеть, не выполняются ли операторы или операторы switch для неопределенного значения перечисления.

Просто помните, что по умолчанию enum - это не более чем обертка вокруг INT, и проверяйте его так же, как если бы он был int.

Для более подробного обсуждения правильного использования enum, вы можете проверить сообщения в блоге Брэда Абрамса и Кшиштофа Квалины или их превосходную книгу "Руководство по разработке структуры: условные обозначения, идиомы и шаблоны для многократно используемых библиотек .NET"

1 голос
/ 27 февраля 2009

Если вы хотите расширить перечисление новыми значениями в будущих версиях вашей библиотеки, не следует использовать конструкцию

if (Enum.IsDefined (typeof (BookCategory), cat))

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

См. Эта статья в блоге для получения дополнительной информации.

1 голос
/ 27 февраля 2009

Это потому, что вполне законно называть этот метод "Test" следующим образом:

Test((BookCategory)-999);

Это приведет к -999 как BookCategory, но, конечно, результат (переданный как параметр "cat" в Test) не является допустимым значением для перечисления BookCategory.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...