Bagaimana cara memasukkan int ke enum?


Jawaban:


3794

Dari sebuah 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);

31
@ FlySwat, bagaimana jika YourEnumdinamis dan hanya akan diketahui saat runtime, dan apa yang saya inginkan adalah konversi Enum?
Shimmy Weitzhandler

226
Ketahuilah bahwa Enum.Parse TIDAK akan berfungsi jika kode Anda dikaburkan. Pada saat run time setelah kebingungan, string dibandingkan dengan nama enum, dan pada titik ini nama enum tidak seperti yang Anda harapkan. Penguraian Anda akan gagal jika sebelumnya berhasil.
jropella

158
WASPADALAH Jika Anda menggunakan sintaks "dari string" di atas dan meneruskan string yang tidak valid yang berupa angka (mis. "2342342" - dengan asumsi itu bukan nilai enum Anda), itu sebenarnya akan memungkinkan tanpa melemparkan kesalahan! Enum Anda akan memiliki nilai itu (2342342) meskipun itu bukan pilihan yang valid di enum itu sendiri.
JoeCool

132
Saya pikir jawaban ini agak tanggal sekarang. Untuk string, Anda harus benar-benar menggunakan var result = Enum.TryParse(yourString, out yourEnum)saat ini (dan memeriksa hasilnya untuk menentukan apakah konversi gagal).
Justin T Conroy

20
Dimungkinkan juga untuk Enum.Parsemenjadi case-insensitive dengan menambahkan truenilai parameter pada panggilan:YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
Erik Schierboom

900

Hanya melemparkannya:

MyEnum e = (MyEnum)3;

Anda dapat memeriksa apakah jangkauannya menggunakan Enum.IsDefined :

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

218
Berhati-hatilah, Anda tidak dapat menggunakan Enum.IsDefined jika Anda menggunakan atribut Flags dan nilainya adalah kombinasi dari flags misalnya: Keys.L | Keys.Control
dtroy

15
Mengenai hal ini Enum.IsDefined, ketahuilah bahwa itu bisa berbahaya: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
adrian

3
Saya lebih suka definisi ini: "Mengembalikan indikasi apakah konstanta dengan nilai yang ditentukan ada dalam enumerasi yang ditentukan" dari MSDN
Pap

3
... Karena definisi Anda dapat menyesatkan, karena Anda mengatakan: "... periksa apakah ada dalam kisaran ..." yang menyiratkan dalam kisaran angka dengan batas awal dan akhir ...
Pap

3
@ mac9416 Saya telah mencoba memberikan contoh singkat di gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - pada dasarnya dengan menggunakan IsDefineduntuk memeriksa nilai input, Anda membuat diri Anda rentan terhadap orang menambahkan nilai enum baru nanti yang akan melewati IsDefinedpemeriksaan (karena baru nilai ada dalam kode baru), tetapi mungkin tidak berfungsi dengan kode asli yang Anda tulis. Oleh karena itu lebih aman untuk secara eksplisit menentukan nilai enum yang dapat ditangani oleh kode Anda.
adrian

238

Atau, gunakan metode ekstensi alih-alih satu baris:

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>();

7
Untuk memproses input pengguna, mungkin ide yang baik untuk memanggil kelebihan Enum.Parse yang memungkinkan Anda menentukan bahwa perbandingan TIDAK peka huruf besar-kecil (yaitu pengguna yang mengetik "merah" (huruf kecil) akan merusak kode di atas tanpa perubahan ini. .)
BrainSlugs83

9
Berguna, tetapi pertanyaannya secara spesifik menanyakan tentang int.
BJury

2
ini juga berfungsi jika string bilangan bulat, misalnya "2"
TruthOf42

2
Ini akan mengeluarkan pengecualian jika enumString adalah null (memiliki masalah yang sama kemarin). Pertimbangkan untuk menggunakan TryParse daripada Parse. TryParse juga akan memeriksa apakah T adalah Tipe Enum
Justin

Jenis metode perluasan ini System.Stringsepertinya seperti polusi namespace
Tn. Anderson

160

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

Bagaimana cara kerjanya?

Enum di .NET adalah struktur yang memetakan serangkaian nilai (bidang) ke tipe dasar (defaultnya adalah int). Namun, Anda sebenarnya dapat memilih tipe integral yang dipetakan oleh enum Anda:

public enum Foo : short

Dalam hal ini enum dipetakan ke shorttipe data, yang berarti enum akan disimpan dalam memori sebagai pendek dan akan berperilaku sebagai pendek ketika Anda menggunakan 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 di Fooatas, tipe value__int16. Ini pada dasarnya berarti bahwa Anda dapat menyimpan apa pun yang Anda inginkan dalam enum, selama jenisnya cocok .

Pada titik ini saya ingin menunjukkan bahwa itu System.Enumadalah tipe nilai, yang pada dasarnya berarti BarFlagakan memakan 4 byte dalam memori dan Fooakan memakan 2 - misalnya ukuran tipe yang mendasarinya (sebenarnya lebih rumit dari itu, tetapi Hei...).

Jawabannya

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

Untuk membuatnya aman, saya pikir itu praktik terbaik untuk mengetahui bahwa tipe yang mendasarinya adalah sama atau secara implisit dapat dikonversi dan untuk memastikan nilai enum ada (mereka tidak diperiksa secara default!).

Untuk melihat cara kerjanya, 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 casting e2juga berfungsi! Dari perspektif kompiler di atas ini masuk akal: value__bidang hanya diisi dengan 5 atau 6 dan ketika Console.WriteLinepanggilan ToString(), nama e1diselesaikan sementara nama e2tidak.

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

Perhatikan juga bahwa saya eksplisit tentang tipe enum yang mendasarinya, meskipun kompiler benar-benar memeriksa ini. Saya melakukan ini untuk memastikan saya tidak mengalami kejutan di jalan. Untuk melihat kejutan ini dalam tindakan, Anda dapat menggunakan kode berikut (sebenarnya saya sering melihat ini terjadi 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();
}

7
Saya menyadari ini adalah posting lama, tetapi bagaimana Anda mendapatkan tingkat pengetahuan ini di c #? Apakah ini dari membaca spesifikasi C #?
Rolan

20
@Rolan Saya terkadang berharap lebih banyak orang akan menanyakan hal itu. :-) Sejujurnya saya tidak begitu tahu; Saya mencoba memahami cara kerja dan mendapatkan informasi di mana pun saya bisa mendapatkannya. Saya memang membaca standar C #, tetapi saya juga secara teratur mendekompilasi kode dengan Reflector (saya bahkan sering melihat kode assembler x86) dan melakukan banyak eksperimen kecil. Juga, mengetahui tentang bahasa lain membantu dalam hal ini; Saya telah melakukan CS selama sekitar 30 tahun sekarang, dan pada titik tertentu hal-hal tertentu menjadi 'logis' - f.ex. enum harus merupakan tipe integral, karena jika tidak interop akan pecah (atau kinerja Anda akan sia-sia).
atlaste

9
Saya percaya kunci untuk melakukan rekayasa perangkat lunak dengan benar adalah mengetahui cara kerja barang. Bagi saya itu berarti bahwa jika Anda menulis sepotong kode, Anda tahu cara menerjemahkannya secara kasar ke f.ex. operasi prosesor dan memori mengambil / menulis. Jika Anda bertanya bagaimana untuk mencapai tingkat itu, saya sarankan membangun satu ton kasus uji kecil, membuatnya lebih keras saat Anda pergi, cobalah untuk memprediksi hasilnya setiap waktu, dan mengujinya setelah itu (termasuk dekompilasi, dll). Setelah mencari tahu semua detail dan semua karakteristik, Anda dapat memeriksa apakah Anda sudah benar dalam standar (membosankan). Setidaknya, itu akan menjadi pendekatan saya.
atlaste

1
Jawaban yang fantastis, terima kasih! Dalam contoh kode terakhir Anda, ia mengeluarkan exception pada saat runtime karena o adalah objek. Anda bisa melemparkan variabel int ke pendek selama itu jatuh dalam kisaran pendek.
gravidThoughts

@gravidTerima kasih. Sebenarnya ini adalah operasi unboxing, sehingga tidak akan melakukan konversi tersirat seperti yang Anda gambarkan. Casting kadang membingungkan dalam C # jika Anda tidak tahu detailnya ... Bagaimanapun, karena int! = short, Ia akan melempar (pembatalan kotak gagal). Jika Anda melakukannya object o = (short)5;, itu akan berhasil, karena jenisnya akan cocok. Ini bukan tentang kisaran, ini tentang jenis.
atlaste


64

Saya menggunakan potongan kode ini untuk memberikan int ke enum saya:

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

Saya menemukannya solusi terbaik.


1
ini bagus. saya terkejut tidak ada pengecualian saat memberikan nilai yang tidak valid ke enum yang didukung int.
orion elenzil

Ini sebenarnya tidak jauh berbeda dari jawaban berperingkat teratas. Jawaban itu juga membahas penggunaan Enum. Ditentukan setelah Anda memasukkan string ke tipe Enum. Jadi, bahkan jika string dicor tanpa kesalahan, Enum. Telah ditentukan masih akan menangkapnya
Don Cheadle

53

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;
    }
}

47

Untuk nilai numerik, ini lebih aman karena akan mengembalikan objek apa pun yang terjadi:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}

Tidak bekerja untuk bendera enum
Seyed Morteza Mousavi


35

Jika Anda memiliki integer yang bertindak sebagai bitmask dan bisa mewakili satu atau lebih nilai dalam enumerasi [Bendera], Anda bisa menggunakan kode ini untuk mem-parsing nilai flag individual ke dalam daftar:

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

Perhatikan bahwa ini mengasumsikan bahwa tipe yang mendasari enumadalah integer 32-bit yang ditandatangani. Jika itu adalah tipe numerik yang berbeda, Anda harus mengubah hardcoded 32 untuk mencerminkan bit dalam tipe itu (atau secara terprogram menurunkannya menggunakan Enum.GetUnderlyingType())


1
Apakah loop ini tidak pernah berakhir? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. Dengan kata lain, nilainya akan selalu lebih rendah dari 0x80000000 karena melimpah ke nol setelah kasus di mana bit D31 = 1. Kemudian, tetap 0 selamanya karena bergeser ke kiri nilai 0 memberi 0
Christian Gingras

Tangkapan besar @christiangingras, terima kasih! Saya telah memodifikasi jawaban untuk akun untuk itu, dan itu harus diperhitungkan ketika bit tertinggi diatur (yaitu 0x80000000 / Int32.MinValue)
Evan M

27

Terkadang Anda memiliki objek dengan MyEnumtipe tersebut. Suka

var MyEnumType = typeof(MyEnumType);

Kemudian:

Enum.ToObject(typeof(MyEnum), 3)

26

Ini adalah metode pengubahan tanda sadar konversi bendera:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

3
Ini sekarang dapat ditingkatkan dengan C # 7.3 dengan membatasi Enumalih-alih struct, artinya kita tidak harus bergantung pada pemeriksaan runtime!
Scott

20

masukkan deskripsi gambar di sini

Untuk mengonversi string menjadi ENUM atau int menjadi ENUM, kita perlu menggunakan fungsi Enum.Parse. Ini adalah video youtube https://www.youtube.com/watch?v=4nhx4VwdRDk yang sebenarnya menunjukkan dengan string dan hal yang sama berlaku untuk int.

Kode berjalan seperti yang ditunjukkan di bawah ini di mana "merah" adalah string dan "MyColors" adalah warna ENUM yang memiliki konstanta warna.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");

20

Sedikit menjauh dari pertanyaan awal, tetapi saya menemukan jawaban untuk pertanyaan Stack Overflow Dapatkan nilai int dari enum berguna. Buat kelas statis dengan public const intproperti, yang memungkinkan Anda untuk dengan mudah mengumpulkan sekelompok intkonstanta terkait , dan kemudian tidak harus membuangnya intsaat menggunakannya.

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

Jelas, beberapa fungsionalitas tipe enum akan hilang, tetapi untuk menyimpan sekelompok konstanta id database, sepertinya solusi yang cukup rapi.


5
enum menggantikan penggunaan konstanta integer seperti ini karena mereka memberikan lebih banyak tipe keselamatan
Paul Richards

1
Paul, ini adalah metode mengumpulkan konstanta int terkait (misalnya Database id constants) sehingga mereka dapat digunakan secara langsung tanpa harus membuangnya ke int setiap kali mereka digunakan. Tipe mereka adalah integer, bukan misalnya, DatabaseIdsEnum.
Ted

1
Setidaknya ada satu situasi yang saya temukan di mana keselamatan tipe enum dapat secara tidak sengaja dilewati.
Thierry

Tetapi enum juga memastikan nilainya unik, sesuatu yang kurang dari pendekatan ini
derHugo

15

Ini mem-parsing bilangan bulat atau string ke target enum dengan pencocokan parsial di dot.NET 4.0 menggunakan obat generik seperti pada kelas utilitas Tawani di atas. Saya menggunakannya untuk mengubah variabel saklar baris perintah yang mungkin tidak lengkap. Karena enum tidak boleh nol, Anda harus memberikan nilai default secara logis. Ini bisa disebut seperti ini:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Berikut kodenya:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

FYI: Pertanyaannya adalah tentang bilangan bulat, yang tidak ada yang disebutkan juga akan secara eksplisit dikonversi di Enum.TryParse ()


13

Dari string: (Enum.Parse kedaluwarsa, gunakan Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}

4
Pertanyaannya secara khusus menanyakan tentang bilangan bulat.
BJury

4
Akankah Yu mengedit jawaban Anda untuk memberi tahu semua orang tentang Enum.TryParse akan mengerjakan untaian nilai atau nama enum (Saya tidak bisa menolak)
JeremyWeir

1
Jeremy, Weir mengerjakannya (tidak bisa menahan keduanya).
huysentruitw

11

Berikut ini adalah metode ekstensi yang sedikit lebih baik

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }

10

Dalam kasus saya, saya perlu mengembalikan enum dari layanan WCF. Saya juga membutuhkan nama yang ramah, bukan hanya enum.ToString ().

Inilah Kelas WCF saya.

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

Inilah metode Extension yang mendapatkan Deskripsi dari Enum.

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

Penerapan:

return EnumMember.ConvertToList<YourType>();

9

Saya tidak tahu lagi dari mana saya mendapatkan bagian dari ekstensi enum ini, tetapi dari stackoverflow. Saya minta maaf untuk ini! Tetapi saya mengambil yang ini dan memodifikasinya untuk enum dengan Bendera. Untuk enum dengan Bendera saya melakukan ini:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

Contoh:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;

9

Anda harus membangun beberapa jenis relaksasi yang cocok agar lebih kuat.

public static T ToEnum<T>(dynamic value)
{
    if (value == null)
    {
        // default value of an enum is the object that corresponds to
        // the default value of its underlying type
        // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
        value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
    }
    else if (value is string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    return (T)Enum.ToObject(typeof(T),
             Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}

Kasus cobaan

[Flags]
public enum A : uint
{
    None  = 0, 
    X     = 1 < 0,
    Y     = 1 < 1
}

static void Main(string[] args)
{
    var value = EnumHelper.ToEnum<A>(7m);
    var x = value.HasFlag(A.X); // true
    var y = value.HasFlag(A.Y); // true

    var value2 = EnumHelper.ToEnum<A>("X");

    var value3 = EnumHelper.ToEnum<A>(null);

    Console.ReadKey();
}

Ini jawaban yang bagus. Ini memalukan sejauh ini sampai di halaman saat ini!
MikeBeaton

8

Berbagai cara dilemparkan ke dan dari Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}

8

Ini dapat membantu Anda mengonversi data input apa pun ke enum yang diinginkan pengguna . Misalkan Anda memiliki enum seperti di bawah ini yang secara default int . Harap tambahkan nilai Default di awal enum Anda. Yang digunakan pada medthod helper ketika tidak ditemukan kecocokan dengan nilai input.

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

NB: Di sini saya mencoba mem-parsing nilai ke int, karena enum secara default int Jika Anda mendefinisikan enum seperti ini yang merupakan tipe byte .

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

Anda perlu mengubah metode parsing at helper dari

int.TryParse(value.ToString(), out  tempType)

untuk

byte.TryParse(value.ToString(), out tempType)

Saya memeriksa metode saya untuk input berikut

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

maaf untuk bahasa inggris saya


8

Inilah metode ekstensi yang digunakan Int32untuk Enum.

Itu menghormati bendera bitwise bahkan ketika nilainya lebih tinggi dari maksimum yang mungkin. Misalnya jika Anda memiliki enum dengan kemungkinan 1 , 2 , dan 4 , tetapi intnya adalah 9 , ia memahami bahwa sebagai 1 tanpa adanya 8 . Ini memungkinkan Anda melakukan pembaruan data sebelum pembaruan kode.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }

6

cara mudah dan jelas untuk menampilkan int ke enum di c #:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }

6

Anda cukup menggunakan Konversi konversi Cast int ke enum atau enum ke int

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine((int)Number.three); //Output=3

        Console.WriteLine((Number)3);// Outout three
        Console.Read();
    }

    public enum Number
    {
        Zero = 0,
        One = 1,
        Two = 2,
        three = 3
    }
}

4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SamplePrograme
{
    public class Program
    {
        public enum Suit : int
        {
            Spades = 0,
            Hearts = 1,
            Clubs = 2,
            Diamonds = 3
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));

            //from int
            Console.WriteLine((Suit)1);

            //From number you can also
            Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
        }
    }
}

3

Anda cukup melakukan seperti di bawah ini:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

Untuk memastikan bahwa Anda hanya memberikan nilai yang benar dan Anda dapat melemparkan pengecualian:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

Perhatikan bahwa menggunakan IsDefined mahal dan bahkan lebih dari sekadar casting, jadi itu tergantung pada implementasi Anda untuk memutuskan untuk menggunakannya atau tidak.


3

Anda dapat menggunakan metode ekstensi.

public static class Extensions
{

    public static T ToEnum<T>(this string data) where T : struct
    {
        if (!Enum.TryParse(data, true, out T enumVariable))
        {
            if (Enum.IsDefined(typeof(T), enumVariable))
            {
                return enumVariable;
            }
        }

        return default;
    }

    public static T ToEnum<T>(this int data) where T : struct
    {
        return (T)Enum.ToObject(typeof(T), data);
    }
}

gunakan kode seperti di bawah ini

enum:

public enum DaysOfWeeks
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
}

Penggunaan:

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.