Pertanyaan Transmisikan ke enum di C #


Bagaimana bisa sebuah int dilemparkan ke enum di C #?


2565
2017-08-27 03:58


asal


Jawaban:


Dari string:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);
// the foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
  throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")

Dari int:

YourEnum foo = (YourEnum)yourInt;

Memperbarui:

Dari nomor Anda juga bisa

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

3115
2017-08-27 03:59



Hanya mentransmisikannya:

MyEnum e = (MyEnum)3;

Anda dapat memeriksa apakah itu dalam jangkauan menggunakan Enum.IsDefined:

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }

718
2017-08-27 04:01



Alternatifnya, gunakan metode ekstensi, bukan satu-liner:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

Pemakaian:

Color colorEnum = "Red".ToEnum<Color>();

ATAU

string color = "Red";
var colorEnum = color.ToEnum<Color>();

197
2017-11-11 13:27



Saya pikir untuk mendapatkan jawaban yang lengkap, orang harus tahu bagaimana kerja enum internal. NET.

Bagaimana cara kerjanya

Enum di. NET adalah struktur yang memetakan seperangkat nilai (bidang) ke tipe dasar (defaultnya adalah int). Namun, Anda benar-benar dapat memilih jenis integral yang enum Anda peta ke:

public enum Foo : short

Dalam hal ini enum dipetakan ke short tipe data, yang berarti itu akan disimpan dalam memori sebagai pendek dan akan berperilaku singkat ketika Anda mentransmisikan dan menggunakannya.

Jika Anda melihatnya dari sudut pandang IL, enum (normal, int) terlihat seperti ini:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

Apa yang harus mendapat perhatian Anda di sini adalah bahwa value__ disimpan secara terpisah dari nilai enum. Dalam kasus enum Foo di atas, jenis value__ int16. Ini pada dasarnya berarti Anda dapat menyimpan apa pun yang Anda inginkan dalam sebuah enum, selama jenisnya cocok.

Pada titik ini saya ingin menunjukkan hal itu System.Enum adalah tipe nilai, yang pada dasarnya berarti itu BarFlag akan mengambil 4 byte dalam memori dan Foo akan mengambil 2 - mis. ukuran jenis yang mendasari (sebenarnya lebih rumit dari itu, tapi hei ...).

Jawabannya

Jadi, jika Anda memiliki integer yang ingin Anda petakan ke enum, runtime hanya harus melakukan 2 hal: salin 4 byte dan beri nama lain (nama enum). Menyalin adalah implisit karena data disimpan sebagai jenis nilai - ini pada dasarnya berarti bahwa jika Anda menggunakan kode tidak dikelola, Anda dapat dengan mudah mengganti enum dan bilangan bulat tanpa menyalin data.

Untuk membuatnya aman, saya pikir ini adalah praktik terbaik tahu bahwa jenis yang mendasari adalah konversi yang sama atau implisit dan untuk memastikan nilai enum ada (mereka tidak diperiksa secara default!).

Untuk melihat bagaimana ini bekerja, coba kode berikut:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

Perhatikan bahwa mentransmisikan ke e2 juga berfungsi! Dari perspektif kompilator di atas ini masuk akal: value__ bidang hanya diisi dengan 5 atau 6 dan kapan Console.WriteLine panggilan ToString(), nama dari e1 diselesaikan sementara nama e2 tidak.

Jika bukan itu yang Anda inginkan, gunakan Enum.IsDefined(typeof(MyEnum), 6) untuk memeriksa apakah nilai Anda mentransmisikan peta ke enum yang ditentukan.

Juga perhatikan bahwa saya eksplisit tentang jenis enum yang mendasari, meskipun compiler benar-benar memeriksa ini. Saya melakukan ini untuk memastikan saya tidak mengalami kejutan apa pun di jalan. Untuk melihat kejutan ini dalam tindakan, Anda dapat menggunakan kode berikut (sebenarnya saya pernah melihat ini terjadi banyak dalam kode basis data):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

116
2018-04-03 07:39



Ambil contoh berikut:

int one = 1;
MyEnum e = (MyEnum)one;

89
2017-08-27 04:00



Saya menggunakan kode ini untuk mentransmisikan int ke enum saya:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

Saya merasa ini solusi terbaik.


54
2017-10-21 10:05



Di bawah ini adalah kelas utilitas yang bagus untuk Enums

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}

44
2017-09-07 04:42