Konversi Enum ke String

163

Yang merupakan cara yang disukai untuk mengubah Enum ke String di. NET 3.5?

  • Enum.GetName
  • Enum.Format
  • ToString

Mengapa saya harus memilih salah satu dari ini daripada yang lain? Apakah seseorang berkinerja lebih baik?

Eric Weilnau
sumber
10
Saya mencari dan tidak dapat menemukan duplikat. Jika Anda dapat memberikan tautan, saya akan menghapus pertanyaan ini.
Eric Weilnau,
1
kadang-kadang, menggunakan pernyataan switch bukan praktik terbaik (ketika Anda memiliki enumerasi besar), Anda dapat menggunakan Dict <> sebagai gantinya
Guy L
1
Jika Anda menginginkan kinerja yang lebih baik, Anda dapat menggunakan kelas yang dijelaskan dalam artikel ini codeproject.com/KB/dotnet/enum.aspx . Penggunaan akan terlihat seperti Enum ini <YourEnum> .ToString (YourValue) atau Enum <YourEnum> .ToString ((int) YourValue)
ideafixxxer
5
Pengodean untuk tidak merusak dotfuscation adalah lambang dari ekor yang mengibas-ngibaskan anjing. Produser SW tidak berpikir, "Ayo buat aplikasi hebat jadi dotfuscator ada hubungannya." Dofuscator ada untuk membantu memfasilitasi pengembangan SW. Jika tidak bisa melakukan itu ... bisakah!
micahhoover

Jawaban:

125

Pada C # 6 cara terbaik untuk mendapatkan nama enum adalah nameofoperator baru :

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

Ini berfungsi pada waktu kompilasi, dengan enum digantikan oleh string dalam hasil kompilasi, yang pada gilirannya berarti ini adalah cara tercepat yang mungkin.

Penggunaan nama enum apa pun mengganggu kebingungan kode, jika Anda menganggap kebingungan nama enum bermanfaat atau penting - itu mungkin pertanyaan lain.

Keith
sumber
11
Ini patut mendapat perhatian lebih. Batasan yang jelas meskipun demikian, yaitu persyaratan untuk input waktu kompilasi. Menurut pendapat saya ini harus lebih disukai bila memungkinkan . 'Ubah nama' dan 'temukan semua referensi' memperhitungkannya juga, berpotensi menghindari string sihir dan konstanta duplikat.
Timo
1
Jadi saya kira itu tidak akan berfungsi ketika nilai enum didefinisikan pada saat runtime? Contoh: MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter
1
@ Maxax tidak, seperti yang nameof(variableEnum)akan terjadi "variableEnum". Ini mencerminkan (saat membangun) nama bidang / properti / param / variabel bukan nilai .
Keith
kamu. sayangnya tidak berfungsi jika Anda melakukan ini: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Secara jelas
@Sangat ya, itu akan kembali "someEnumValue", sementara Anda harus nameof(SomeEnum.FooBar)mendapatkannya "FooBar".
Keith
93

Bekerja untuk proyek kami ...

public static String convertToString(this Enum eff)
{
    return Enum.GetName(eff.GetType(), eff);
}

public static EnumType converToEnum<EnumType>(this String enumValue)  
{
    return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}
Sumtraveller
sumber
7
Enum.GetName mengambil nilai sebagai argumen objek. Ini berarti bahwa nilainya akan kotak dan ini akan membuang sumber daya CPU pada alokasi dan pada pengumpulan sampah. Jika ini dilakukan banyak waktu, Enum.GetName akan memiliki throughput yang jauh lebih rendah daripada caching nilai dalam kamus dan mencari nama di sana.
Berlari
@Bisa jadi apa solusinya, yang mana yang harus digunakan?
shaijut
Ini seharusnya jawabannya
Secara jelas
membuat proyek saya lebih lambat. toString () lebih cepat.
d2k2
29

Dalam pengujian saya, Enum.GetNamelebih cepat dan dengan margin yang layak. ToStringPanggilan internal Enum.GetName. Dari sumber untuk .NET 4.0, yang penting:

public override String ToString()
{
     return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}

private static String InternalFormat(RuntimeType eT, Object value)
{
    if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
    {
        String retval = GetName(eT, value); //<== the one
        if (retval == null)
            return value.ToString();
        else
            return retval;
    }
    else
    {
        return InternalFlagsFormat(eT, value);
    }
}

Saya tidak bisa mengatakan itu adalah alasan yang pasti, tetapi tes menyatakan satu lebih cepat dari yang lain. Kedua panggilan tersebut melibatkan tinju (sebenarnya itu adalah panggilan refleksi, Anda pada dasarnya mengambil nama bidang) dan bisa lambat sesuai dengan keinginan Anda.

Setup tes : enum dengan 8 nilai, no. iterasi = 1000000

Hasil : Enum.GetName => 700 ms, ToString => 2000 ms

Jika kecepatan tidak terlihat, saya tidak akan peduli dan menggunakannya ToStringkarena menawarkan panggilan yang jauh lebih bersih. Kontras

Enum.GetName(typeof(Bla), value)

dengan

value.ToString()
nawfal
sumber
25

Enum.GetName (...)

Ini adalah metode paling elegan yang dimaksudkan untuk itu.

var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);

Meskipun saya tidak melihat masalah dengan panggilan .ToString()karena itu hanya lebih pendek.

var enumValueString = MyEnum.MyValue.ToString();

Dengan sintaks C # 6 baru Anda dapat menggunakan:

nameof(MyEnum.MyValue)
Andrei
sumber
20

Semua ini secara internal akhirnya memanggil metode yang disebut InternalGetValueAsString. Perbedaan antara ToStringdan GetNameyang GetNameharus memverifikasi beberapa hal pertama:

  1. Jenis yang Anda masukkan bukan nol.
  2. Jenis yang Anda masukkan sebenarnya adalah enumerasi.
  3. Nilai yang Anda berikan bukan nol.
  4. Nilai yang Anda berikan adalah tipe yang dapat digunakan oleh enumerasi sebagai tipe yang mendasarinya, atau tipe enumerasi itu sendiri. Ini digunakan GetTypepada nilai untuk memeriksa ini.

.ToStringtidak perlu khawatir tentang masalah-masalah di atas, karena ini dipanggil pada instance dari kelas itu sendiri, dan bukan pada versi yang disahkan, oleh karena itu, karena fakta bahwa .ToStringmetode ini tidak memiliki masalah verifikasi yang sama sebagai metode statis, saya akan menyimpulkan itu .ToStringadalah cara tercepat untuk mendapatkan nilai sebagai string.

David Morton
sumber
2
Di mana Anda memeriksa ini? Apa versi perakitannya? Saya mendapatkan hasil yang sangat berbeda.
nawfal
17

Yang terbaik yang dapat saya temukan adalah pertanyaan yang tidak terkait ini di MSDN , yang berisi potongan XML yang menjawab pertanyaan ini. Setiap metode ini memiliki kelemahan yang sama: mereka memanggil enum.toString(), yang tidak berfungsi dengan baik saat menggunakan Dotfuscation . Kekhawatiran lain tampaknya terkait dengan tinju tidak langsung (GetName dan Format). Sayangnya, saya tidak dapat menemukan alasan kinerja untuk menggunakan salah satu di atas.

Mengutip dari cuplikan xml ,

Melewati enum kotak ke string.Format () atau fungsi lainnya dapat mengakibatkan enum.ToString()dipanggil. Ini akan menyebabkan masalah saat Dotfuscating. Anda tidak harus menggunakan enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()atau enum.Parse()untuk mengkonversi enum ke string. Alih-alih, gunakan pernyataan peralihan, dan internasionalkan nama jika perlu.

jpaugh
sumber
16

Enum.GetName()

Format()benar-benar hanya pembungkus sekitar GetName()dengan beberapa fungsi pemformatan (atau InternalGetValueAsString()tepatnya). ToString()hampir sama dengan Format(). Saya pikir GetName()ini pilihan terbaik karena sangat jelas apa yang dilakukannya bagi siapa saja yang membaca sumbernya.

Tamas Czinege
sumber
8

Saya membuat metode ekstensi "Deskripsi" dan melampirkannya pada enum sehingga saya bisa mendapatkan penamaan yang benar-benar user-friendly yang mencakup spasi dan casing. Saya tidak pernah suka menggunakan nilai enum itu sendiri sebagai teks yang dapat ditampilkan karena ini adalah sesuatu yang kami pengembang gunakan untuk membuat kode yang lebih mudah dibaca. Itu tidak dimaksudkan untuk tujuan tampilan UI. Saya ingin dapat mengubah UI tanpa melalui dan mengubah enum di seluruh.

TarianDengan Bambu
sumber
6

Saya tidak tahu apa metode "pilihan" itu (tanyakan 100 orang dan dapatkan 100 pendapat berbeda) tetapi lakukan apa yang paling sederhana dan apa yang berhasil. GetNameberfungsi tetapi membutuhkan lebih banyak penekanan tombol. ToString()tampaknya melakukan pekerjaan dengan sangat baik.

Perry Neal
sumber
1

Untuk penggemar VB:

EnumStringValue = System.Enum.GetName(GetType(MyEnum), MyEnumValue)
GlennG
sumber
0

Ini akan berhasil juga.

    List<string> names = Enum.GetNames(typeof(MyEnum)).ToList();
Nic
sumber
0

ToString()memberikan hasil paling jelas dari perspektif keterbacaan, saat menggunakanEnum.GetName() membutuhkan sedikit penguraian mental untuk dengan cepat memahami apa yang coba dilakukan (kecuali jika Anda melihat polanya sepanjang waktu).

Dari sudut pandang kinerja murni, seperti yang sudah disediakan dalam jawaban @ nawfal, Enum.GetName()lebih baik.

Jika kinerja benar-benar tujuan Anda, akan lebih baik untuk menyediakan pencarian sebelumnya (menggunakan Kamus atau pemetaan lainnya).

Dalam C ++ / CLI, ini akan terlihat seperti

Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
    mapping.Add(Enum::GetName(MyEnum::typeid), field);
}

Perbandingan menggunakan enum 100 item dan iterasi 1000000:

Enum.GetName: ~ 800ms
.ToString (): ~ 1600ms
Kamus pemetaan: ~ 250ms

John Go-Soco
sumber
-2

Sederhana: enum nama ke dalam Daftar:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()
Brian
sumber
Hai @Brian, saya rasa Anda tidak perlu menampilkan output dari GetNames ()
Nic