Rzutowanie na Enum z niepewnego źródła

TLDR

Gdy MyEnum nie ma wartości -13, to poniższy kod się wykona poprawnie i w enumie będziemy mieli wartość spoza zakresu enuma.

    var myEnum = (MyEnum) -13;

Właściwa treść

Mamy enum:

enum MyEnum
{
    One = 1
}

I chcemy wykonać prostą operacje utworzenia tego enuma, tyle że posiadamy jedynie wartość liczbową (z zewnętrznego źródła danych). Akurat tak pechowo się stało, że mamy nie istniejącą wartość

    var myEnum = (MyEnum) 13;

Enum casted from invalid value
incorrectEnum po takim rzutowaniu ma nieprawidłową wartość. Nie tego spodziewamy się po Enumie!

Tak po prostu działa C# i warto o tym wiedzieć. Do sprawdzania takich przypadków służy funkcja IsDefined()

    Enum.IsDefined(typeof (MyEnum), -1)

Strzorzyłem funkcję opakowująca zgodną ze standardem

bool TryParse(value, out DesiredType desiredValue)

która wygląda tak:

        public static bool TryConvert<TEnum>(int intValue, out TEnum enumValue) where TEnum : struct
        {
            if (typeof(TEnum).IsEnum == false)
            {
                throw new ArgumentException("TryConvert works only for Enum types");
            }

            if (Enum.IsDefined(typeof(TEnum), intValue) == false)
            {
                enumValue = default(TEnum);
                return false;
            }

            var value = (object)intValue; // casting to object is workaround, cannot do: 
            enumValue = (TEnum)value;     // enumValue = (TEnum)intValue;

            return true;
        }

Pierwsze sprawdzanie możemy wyrzucić. Dodałem je ponieważ nie można wymusić aby typ generyczny był Enum, więc to jest jedyny sposób aby się upewnić że ktoś nie posłał tam dowolnej struktury.

Funkcja Enum.IsDefined() korrzysta z refleksji, więc będzie wolniejsza.

Reklamy
Ten wpis został opublikowany w kategorii Programowanie i oznaczony tagami , , , , . Dodaj zakładkę do bezpośredniego odnośnika.

2 odpowiedzi na „Rzutowanie na Enum z niepewnego źródła

  1. Pingback: dotnetomaniak.pl

  2. chrisseroka pisze:

    Czasem, w zależności od kontekstu, można skorzystać z Enum.TryParse, które pobiera nazwę lub wartość enuma, ale jako ‚string’

Możliwość komentowania jest wyłączona.