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?
Enum .NET 3.5'te bir dizeye dönüştürmek için tercih edilen yolu nedir?
Neden bunlardan birini diğerlerine tercih etmeliyim? Kişi daha iyi performans gösterir mi?
Yanıtlar:
C # 6'dan itibaren bir numaralandırma adını almanın en iyi yolu yeni nameof
operatö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.
nameof(variableEnum)
gibi "variableEnum"
. Değeri değil, alan / özellik / param / değişkenin adını ( derleme zamanında) yansıtır .
"someEnumValue"
ihtiyacınız olacağını ise, nameof(SomeEnum.FooBar)
elde etmek "FooBar"
.
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);
}
Testlerimde, Enum.GetName
daha hızlı ve iyi bir marj vardı. Dahili ToString
aramalar 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()
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)
Bunların hepsi dahili olarak adlandırılan bir yöntemi çağırır InternalGetValueAsString
. Arasındaki fark ToString
ve GetName
olurdu GetName
ilk bir kaç şey doğrulamak zorundadır:
GetType
kontrol etmek için değeri kullanır ..ToString
bu 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 .ToString
yöntemin aynı doğrulama sorunlarına sahip olmaması nedeniyle statik yöntemler olarak, .ToString
değeri bir dize olarak almanın en hızlı yolu olduğu sonucuna varıyorum .
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ızenum.ToString()
,enum.GetNames()
,enum.GetName()
,enum.Format()
veyaenum.Parse()
bir dizeye Bir enum dönüştürmek. Bunun yerine, bir switch ifadesi kullanın ve gerekirse adları uluslararası hale getirin.
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.
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.
"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.
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