Numaralandırmayı Dizeye Dönüştür


163

Enum .NET 3.5'te bir dizeye dönüştürmek için tercih edilen yolu nedir?

  • Enum.GetName
  • Enum.Format
  • ToString

Neden bunlardan birini diğerlerine tercih etmeliyim? Kişi daha iyi performans gösterir mi?


10
Aradım ve bir kopya bulamadım. Bir bağlantı sağlayabilirseniz bu soruyu silerim.
Eric Weilnau

1
bazen, bir switch deyimi kullanarak yerine en iyi uygulama (eğer büyük enumerations varken) Eğer Dict <kullanabilirsiniz> değildir
Guy L

1
Daha iyi performans istiyorsanız, bu makalede açıklanan sınıfı kullanabilirsiniz codeproject.com/KB/dotnet/enum.aspx . Kullanım şöyle sıralanır <YourEnum> .ToString (yourValue) veya Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer

5
Dotfuscation'ı kırmamak için kodlama, köpeği sallayan kuyruğun özüdür. SW üreticileri, "Dotfuscator'ın yapacak bir şeyi olması için harika bir uygulama yapalım" diye düşünmüyor. Dofuscator, SW gelişimini kolaylaştırmaya yardımcı olmak için mevcuttur. Eğer bunu yapamazsa ... yapabilir!
micahhoover

Yanıtlar:


127

C # 6'dan itibaren bir numaralandırma adını almanın en iyi yolu yeni nameofoperatördür:

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

Bu derleme zamanında çalışır, enum derlenmiş sonuçta dize ile değiştirilir, bu da bunun mümkün olan en hızlı yol olduğu anlamına gelir.

Enum adlarının herhangi bir şekilde kullanılması, enum adlarının karıştırılmasının değerli veya önemli olduğunu düşünüyorsanız, muhtemelen başka bir soru.


11
Bu daha fazla ilgiyi hak ediyor. Açık sınırlama, yani derleme zamanı girişi gerekliliğine rağmen. Bence bu mümkün olduğunda tercih edilmelidir . 'Yeniden adlandır' ve 'tüm referansları bul' da bunu dikkate alır ve potansiyel olarak sihirli dizelerden ve yinelenen sabitlerden kaçınır.
Timo

1
Yani sanırım enum değeri çalışma zamanında tanımlandığında işe yaramaz? Örn: MyEnum variableEnum; variableEnum = setEnumValueMethod (); (variableEnum) NameOf;
Maxter

1
@Maxter no, olduğu nameof(variableEnum)gibi "variableEnum". Değeri değil, alan / özellik / param / değişkenin adını ( derleme zamanında) yansıtır .
Keith

ye. ne yazık ki bunu yaparsanız çalışmaz: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
1919'da

1
@Squibly evet, dönecektir "someEnumValue"ihtiyacınız olacağını ise, nameof(SomeEnum.FooBar)elde etmek "FooBar".
Keith

93

Projemiz için çalışıyor ...

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

7
Enum.GetName, değeri bir nesne bağımsız değişkeni olarak alır. Bu, değerin kutulanacağı ve bunun ayırma ve çöp toplama üzerindeki CPU kaynaklarını harcayacağı anlamına gelir. Bu çok zaman yapılırsa, Enum.GetName bir sözlükteki değerleri önbelleğe almak ve oradaki adı aramaktan çok daha düşük bir iş hacmine sahip olacaktır.
Ran

@ Peki bunun yerine hangi çözüm kullanılır?
17'de shaijut

Bu cevap olmalı
19:49

projemi yavaşlatır. toString () daha hızlıdır.
d2k2

29

Testlerimde, Enum.GetNamedaha hızlı ve iyi bir marj vardı. Dahili ToStringaramalar Enum.GetName. .NET 4.0 kaynağından gerekli olan:

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

Bunun kesin nedeni olduğunu söyleyemem, ama testler birinin diğerinden daha hızlı olduğunu söyler. Her iki çağrı da boks içerir (aslında yansıma çağrılarıdır, aslında alan adlarını alırsınız) ve beğeninize göre yavaş olabilir.

Test kurulumu : 8 değer ile numaralandırma, no. iterasyon sayısı = 1000000

Sonuç : Enum.GetName => 700 ms, ToString => 2000 ms

Hız farkedilmezse, ToStringçok daha temiz bir çağrı sunduğu için umursamıyorum ve kullanmam . Kontrast

Enum.GetName(typeof(Bla), value)

ile

value.ToString()

25

Enum.GetName (...)

Bu, bunun için tasarlanan en zarif yöntemdir.

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

Aramakla ilgili herhangi bir sorun görmeme .ToString()rağmen, sadece daha kısa.

var enumValueString = MyEnum.MyValue.ToString();

Yeni C # 6 sözdizimi ile şunları kullanabilirsiniz:

nameof(MyEnum.MyValue)

20

Bunların hepsi dahili olarak adlandırılan bir yöntemi çağırır InternalGetValueAsString. Arasındaki fark ToStringve GetNameolurdu GetNameilk bir kaç şey doğrulamak zorundadır:

  1. Girdiğiniz tür boş değil.
  2. Girdiğiniz tür aslında bir numaralandırmadır.
  3. İletdiğiniz değer boş değil.
  4. İletdiğiniz değer, bir numaralandırmanın altta yatan tür olarak kullanabileceği bir türden veya numaralandırmanın kendisinin türündedir. Bunu GetTypekontrol etmek için değeri kullanır .

.ToStringbu yukarıdaki sorunlardan herhangi biri için endişelenmenize gerek yoktur, çünkü sınıfın kendisinin bir örneğinde çağrılır ve geçirilmiş bir sürümde değil, bu nedenle .ToStringyöntemin aynı doğrulama sorunlarına sahip olmaması nedeniyle statik yöntemler olarak, .ToStringdeğeri bir dize olarak almanın en hızlı yolu olduğu sonucuna varıyorum .


2
bunları nereden kontrol ettin? Montaj sürümü neydi? Çok farklı sonuçlar elde ediyorum.
nawfal

17

Bulabildiğim en iyi şey, bu soruyu cevaplayan bir XML snippet'i içeren MSDN'deki bu ilgisiz soru. Bu yöntemlerden herhangi biri aynı kusuru paylaşır: Dotfuscationenum.toString() kullanırken düzgün çalışmayan çağırırlar . Diğer endişelerin dolaylı boks (GetName ve Format) ile ilgili olduğu görülmektedir. Ne yazık ki, yukarıdakilerden herhangi birini kullanmak için herhangi bir performans nedeni bulamıyorum.

Xml snippet'inden yorumlama ,

Kutulu bir enum'un string.Format () veya başka bir işleve iletilmesi enum.ToString()çağrılabilir. Bu, Dotfuscating sırasında sorunlara neden olacaktır. Sen kullanmamalısınız enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()veya enum.Parse()bir dizeye Bir enum dönüştürmek. Bunun yerine, bir switch ifadesi kullanın ve gerekirse adları uluslararası hale getirin.


16

Enum.GetName()

Format()gerçekten sadece GetName()bazı biçimlendirme işlevselliği (veya InternalGetValueAsString()tam olarak) ile bir sarıcı . ToString()ile hemen hemen aynı Format(). GetName()En iyi seçenek olduğunu düşünüyorum çünkü kaynağı okuyan herkes için ne yaptığı tamamen açık.


8

Ben bir "Açıklama" uzantısı yöntemi oluşturmak ve boşluk ve kasa içeren gerçekten kullanıcı dostu adlandırma alabilirsiniz böylece enum iliştirmek. Geliştiricilerin daha okunabilir kod oluşturmak için kullandığımız bir şey olduğundan, numaralandırma değerini görüntülenebilir metin olarak kullanmayı hiç sevmedim. UI görüntüleme amaçları için tasarlanmamıştır. Ben geçmeden ve her yerinde numaralarını değiştirmeden UI değiştirmek istiyorum.


6

"Tercih edilen" yöntemin ne olduğunu bilmiyorum (100 kişiye sorun ve 100 farklı fikir alın) ama en basit olanı ve neyin işe yaradığını yapın. GetNameçalışır, ancak çok daha fazla tuş vuruşu gerektirir. ToString()işi çok iyi yapıyor gibi görünüyor.


1

VB meraklıları için:

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

0

Bu da işe yarar.

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

0

ToString()kullanırken okunabilirlik perspektifinden en belirgin sonucu verirEnum.GetName() ne yapmaya çalıştığını hızlıca anlamak için biraz daha zihinsel ayrıştırma gerektirir (deseni her zaman görmüyorsanız).

Saf bir performans açısından, @ nawfal'ın cevabında zaten belirtildiği gibi Enum.GetName(), daha iyidir.

Performans gerçekten hedefinizse, önceden bir arama yapmak daha iyi olacaktır (bir Sözlük veya başka bir harita kullanarak).

C ++ / CLI'de bu,

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

100 öğe ve 1000000 iterasyondan oluşan bir numaralandırma kullanarak karşılaştırma:

Enum.GetName: ~
800ms .ToString (): ~ 1600ms
Sözlük eşleme: ~ 250ms


-3

Basit: Bir Listede isimleri isimler:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()

Merhaba @Brian, GetNames ()
Nic
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.