Soru String olarak C # sayısal enum değeri


Aşağıdaki enum var:

public enum Urgency {
    VeryHigh = 1,
    High     = 2,
    Routine  = 4
}

Bir tane getirebilirim enum "değer" dize olarak bunun gibi:

((int)Urgency.Routine).ToString() // returns "4"  

Not: Bu farklıdır:

Urgency.Routine.ToString() // returns "Routine"
(int)Urgency.Routine       // returns 4

Bir sözdizimsel şeker sağlayacak bir uzatma sınıfı veya statik bir utliity sınıfı oluşturabileceğim bir yol var mı? :)


44
2017-08-09 22:33


Menşei


Aradığın şey hakkında daha hassas olabilir misin? - Kirk Woll
yani enumValue.ToValueString () == int değeri? - Kirk Woll
Altta yatan int değeri - ancak bir dize olarak (dizge olarak enum değil) Bir int ve sonra bir dizeye dökümün sözdizimi sözdizimini hatırlamak yerine, bir yöntemi kullanan statik bir sınıf herhangi Enum değeri kullanımı kolaylaştırır. Dilin, peşinde olduğum şeyi desteklemeyeceğinden şüpheleniyorum. - David Moorhouse
.. istediğini yaptım. - spender


Cevaplar:


Enums ToString yönteminin aşırı yüklenmelerini bir biçim dizesi vermek için kullanabilmeniz gerekir, bu enum değerini bir dize olarak basacaktır.

public static class Program
{
    static void Main(string[] args)
    {
        var val = Urgency.High;
        Console.WriteLine(val.ToString("D")); 
    }
}

public enum Urgency 
{ 
    VeryHigh = 1,
    High = 2,
    Low = 4
}

84
2017-08-09 23:23



Bosh. Güzel sadelik. Cevabımı silmek istememi sağlıyor! +1 - spender
Evet, aynı sonucun sorguya farklı bir yaklaşımla sunulmasında yanal düşüncenin güzel tarafı. Kod public static string NumberString(this Enum enVal){return enVal.ToString("D");} fikrinizi almalı ve istenen uzantı yöntemine dönüştürmelidir. - Jon Hanna
Harika şeyler ... Aşağıda cevabımı görün - David Moorhouse
Bunu, uzantı yöntemini kullanan diğerinden daha çok seviyorum. Uzantı yöntemi oluşturarak, sadece kodunuza gereksiz bağımlılık eklersiniz. En az bağımlılık kodunuzu daha iyi hatırlayın! - ktutnik
Birden çok değer için geçerli değerler (örnek): new[] { ProductStatus.Open, ProductStatus.Deprecated }.Select(s => s.ToString("D")) - EriF89


Enumlar için daha "insan tarafından okunabilir" açıklamalar elde etmek için (örneğin, örneğinizde "VeryHigh" yerine "Çok Yüksek"), enum değerlerini aşağıdaki gibi öznitelikle süsledim:

public enum MeasurementType
{
    Each,

    [DisplayText("Lineal Metres")]
    LinealMetre,

    [DisplayText("Square Metres")]
    SquareMetre,

    [DisplayText("Cubic Metres")]
    CubicMetre,

    [DisplayText("Per 1000")]
    Per1000,

    Other
}


public class DisplayText : Attribute
{

    public DisplayText(string Text)
    {
        this.text = Text;
    }


    private string text;


    public string Text
    {
        get { return text; }
        set { text = value; }
    }
}

Sonra böyle bir uzantı yöntemi kullandı:

    public static string ToDescription(this Enum en)
    {

        Type type = en.GetType();

        MemberInfo[] memInfo = type.GetMember(en.ToString());

        if (memInfo != null && memInfo.Length > 0)
        {

            object[] attrs = memInfo[0].GetCustomAttributes(
                                          typeof(DisplayText),

                                          false);

            if (attrs != null && attrs.Length > 0)

                return ((DisplayText)attrs[0]).Text;

        }

        return en.ToString();

    }

Sonra sadece arayabilirsin

myEnum.ToDescription ()
 numaranızı daha okunabilir metin olarak görüntülemek için.


17
2017-08-09 22:54



vay, bu da bu soruna oldukça hasta bir çözüm - Robert Karl
Ben benzer yaptım, genellikle sadece deve-casing konvansiyonuna bağlı. Soruyu soran şeyi yapmaz. - Jon Hanna
Mükemmel cevap, ama sorduğu soru için değil. - Brady Moritz
Teşekkürler - ama int değerini döndürmez - bir dizi olarak :) - David Moorhouse
Bildirgesini eklemediniz. DisplayText bağlıyor. Ekleyebilir misiniz? - Alex Essilfie


Bu enum ile uğraşmak isterseniz Mark Byer'in çözümünü kullanın.

Daha genel bir çözüm için:

public static string NumberString(this Enum enVal) 
{
    return Convert.ToDecimal(enVal).ToString("0");
}

Ondalıklara dönüştürmek, 8 farklı izin verilmiş temel integral türle başa çıkmaya gerek olmadığı anlamına gelir, çünkü bunların tümü dezavantajlı olarak ondalıktan değil, birbirine dönüşür (üstelik ve uzun zamandır kayıpsız bir şekilde dönüşüm yapmazlar, fakat ikisi de Tüm kalan). Bunu yapmak muhtemelen daha hızlı olacaktır (özellikle karşılaştırma sırasına göre seçerseniz), ancak nispeten az kazanç için çok daha fazla verim alacaktır.

Düzenle:

Yukarıdakiler Frankentosh'unki kadar iyi değil, Frankentosh da bu soruyu gerçek sorunla karşılaştı ve çok net bir şekilde çözdü.


4
2017-08-09 23:20





Biraz düşünmeye ne dersin? Altta yatan tüm tiplerle çalışmalıdır.

public static class EnumTools
{
    public static string ToRawValueString(this Enum e)
    {
        return e
            .GetType()
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .First(f => f.Name==e.ToString())
            .GetRawConstantValue()
            .ToString();
    }
}

Sonra:

Console.WriteLine(Urgency.High.ToRawValueString()); //Writes "2"

2
2017-08-09 22:56



Onu almalıyım ... - Robert Karl
İlk olarak (), değer ile eşleşen numaralandırmada tanımlı bir değer yoksa, özellikle bayrak enumları ile ortak olan ve diğer durumlarda (mümkün olduğunda) başarısız olur. Enum.IsDefined(e.GetType(), e) false döndürür) Böyle bir durumda daha savunmasız olmalı ve sonra geri dönüşün geçerli olmayan (başarısızlık) bir değerin üzerinde başarısız olmaması, yansıma görmeme yaklaşımını kullanmak olacaktır. Daha sonra, yansıma bitini daha hızlı olmadıkça silin. - Jon Hanna
@Jon: Enum'un türünün bunun için nasıl bir giriş içermeyeceğini anlamıyorum. Neyi kaçırıyorum? EDIT: Gotcha, Enum ORed bayraklar olabilir. Yorumunuzu kabul ediyorum. - spender
Bu en yaygın durum. Altında yatan türün herhangi bir değerinin bir enum türüne, dolayısıyla Enum.IsDefined () öğesinin, bir yönteme geçersiz bir argüman veya bir özellik için geçersiz bir değer olması durumlarına yakalanmasına izin vermek için var olması da geçerlidir. - Jon Hanna


İsterseniz, uzantı yöntemini tüm enumlar için çalıştırabilirsiniz:

public static string ToValueString(this Enum enumValue) 
{
    if (enumValue.GetType().GetEnumUnderlyingType() == typeof(int))
        return ((int)(object)enumValue).ToString();
    else if (enumValue.GetType().GetEnumUnderlyingType() == typeof(byte))
        return ((byte)(object)enumValue).ToString();
    ... 
}        

2
2017-08-09 22:41



+1: İlginç ... ama aynı anda bu çift döküm görmek için biraz sıradışı. İyi numara. :) Kullanabilir Enum yerine T where T : struct? - Mark Byers
Haklısın. Bu durumda neden yararlı olduğunu düşündüğümden emin değilim. Önerinizi yansıtacak şekilde değiştirildi. - Kirk Woll


Harika şeyler ... Artık projeme bir uzantı yöntemi ekledim

public static class EnumExtensions 
{ 
    public static string NumberString(this Enum enVal) 
    { 
        return enVal.ToString("D"); 
    }
} 

Şimdi int değerini alabilirim - bir dize olarak - arayarak Urgency.Routine.NumberString(); Frankentosh ve Jon'a teşekkürler :)


2
2017-08-10 01:47





Belirli bir tür için bir uzantı yöntemi yazabilirsiniz:

public static class UrgencyExtension
{
    public static string ToIntegerString(this Urgency u)
    {
        return ((int)u).ToString();
    }
}

Aşağıdaki gibi kullanın:

Urgency u = Urgency.Routine;
string s = u.ToIntegerString();

1
2017-08-09 22:38