Приведение целых к перечислениям в C # - PullRequest
35 голосов
/ 18 ноября 2009

Есть кое-что, чего я не могу понять в C #. Вы можете преобразовать int вне диапазона в enum, и компилятор не вздрогнет. Представьте себе это enum:

enum Colour
{
    Red = 1,
    Green = 2,
    Blue = 3
}

Теперь, если вы напишите:

Colour eco;
eco = (Colour)17;

Компилятор считает, что это нормально. И время выполнения тоже. Э-э?

Почему команда C # решила сделать это возможным? Я думаю, что в этом решении отсутствует смысл использования перечислений в сценариях, подобных этому:

void DoSomethingWithColour(Colour eco)
{
    //do something to eco.
}

В языке со строгой типизацией, таком как C #, я хотел бы предположить, что eco всегда будет содержать допустимое значение Colour. Но это не так. Программист может вызвать мой метод со значением 17, присвоенным eco (как в предыдущем фрагменте кода), поэтому код в моем методе не должен предполагать, что eco содержит допустимое значение Colour. Мне нужно проверить это явно и обработать исключительные значения, как мне угодно. Почему это?

По моему скромному мнению, было бы гораздо приятнее, если бы компилятор выдавал сообщение об ошибке (или даже предупреждение) при приведении вне диапазона int в enum, если известно значение int во время компиляции. Если нет, среда выполнения должна выдать исключение в операторе присваивания.

Что ты думаешь? Есть ли причина, почему это так?

(Примечание. Это вопрос Я много лет назад писал в своем блоге , но не получил информативного ответа.)

Ответы [ 12 ]

0 голосов
/ 12 ноября 2010

Я думал, что поделюсь кодом, который я использовал для проверки Enums, так как пока у нас нет ничего, что работает ...

public static class EnumHelper<T>
{
    public static bool IsValidValue(int value)
    {
        try
        {
            Parse(value.ToString());
        }
        catch
        {
            return false;
        }

        return true;
    }

    public static T Parse(string value)
    {
        var values = GetValues();
        int valueAsInt;
        var isInteger = Int32.TryParse(value, out valueAsInt);
        if(!values.Select(v => v.ToString()).Contains(value)
            && (!isInteger || !values.Select(v => Convert.ToInt32(v)).Contains(valueAsInt)))
        {
            throw new ArgumentException("Value '" + value + "' is not a valid value for " + typeof(T));
        }

        return (T)Enum.Parse(typeof(T), value);
    }

    public static bool TryParse(string value, out T p)
    {
        try
        {
            p = Parse(value);
            return true;
        }
        catch (Exception)
        {
            p = default(T);
            return false;
        }

    }

    public static IEnumerable<T> GetValues()
    {
        return Enum.GetValues(typeof (T)).Cast<T>();
    }
}
0 голосов
/ 18 ноября 2009

Будет выдано сообщение об ошибке с использованием Enum.Parse ();

Enum parsedColour = (Colour)Enum.Parse(typeof(Colour), "17");

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

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