İnt numaralandırma nasıl kullanılır?


Yanıtlar:


3792

Bir dizeden:

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.")
}

Bir int'den:

YourEnum foo = (YourEnum)yourInt;

Güncelleme:

Numaradan da yapabilirsiniz

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

31
@FlySwat, dinamikse YourEnumve yalnızca çalışma zamanında bilinecekse ve dönüştürmek istediğim şey Enumnedir?
Shimmy Weitzhandler

226
Kodunuzun gizlenmesi durumunda Enum.Parse'ın ÇALIŞMADIĞINI unutmayın. Gizlemeden sonraki çalışma zamanında dize, numaralandırma adlarıyla karşılaştırılır ve bu noktada numaralandırmaların adları, olmasını beklediğiniz gibi değildir. Sonuç olarak çözümlemeniz daha önce başarılı oldukları yerde başarısız olur.
jropella

158
DİKKAT Yukarıdaki "bir dizeden" sözdizimini kullanırsanız ve bir sayı olan geçersiz bir dize geçirirseniz (örn. "2342342" - numaralandırmanızın bir değeri olmadığını varsayarsak), aslında bir hata atmadan buna izin verir! Numaralandırmanın kendisinde geçerli bir seçim olmasa da, numaralandırmanız bu değere (2342342) sahip olacaktır.
JoeCool

132
Sanırım bu cevap biraz tarihli. Dize için, var result = Enum.TryParse(yourString, out yourEnum)bugünlerde gerçekten kullanmalısınız (ve dönüşümün başarısız olup olmadığını belirlemek için sonucu kontrol etmelisiniz ).
Justin T Conroy

20
Çağrıya Enum.Parsebir trueparametre değeri ekleyerek büyük / küçük harfe duyarsız olmak da mümkündür :YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
Erik Schierboom

900

Sadece yayınla:

MyEnum e = (MyEnum)3;

Menzil içinde olup olmadığını Enum.IsDefined kullanarak kontrol edebilirsiniz :

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

218
Flaum özniteliğini kullanırsanız ve değer örneğin bayrakların bir birleşimi ise Enum.IsDefined kullanamayacağınıza dikkat edin: Keys.L | Keys.Control
dtroy

15
İlgili Enum.IsDefined, bu tehlikeli olabilir unutmayın: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
Adrian

3
: Ben bu tanımı tercih "İade belirtilen bir değere sahip bir sabit belirli bir numaralandırma var olup olmadığını bir göstergesidir" dan MSDN
Pap

3
... Çünkü tanımınız yanıltıcı olabilir, çünkü şöyle diyorsunuz: "... menzil içinde olup olmadığını kontrol edin ..." Bu, başlangıç ​​ve bitiş limitlerine sahip bir dizi sayı anlamına gelir ...
Pap

3
@ mac9416 Ben bir öz örnek vermeye çalıştım gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - temelde kullanarak IsDefinedgiriş değerlerini kontrol etmek, bir geçerdi sonra yeni enum değerler ekleyerek insanlara karşı savunmasız kendinizi bırakın IsDefinedyeni beri çek ( değeri yeni kodda bulunur), ancak yazdığınız orijinal kodla çalışmayabilir. Bu nedenle, kodunuzun işleyebileceği enum değerlerini açıkça belirtmek daha güvenlidir.
adrian

238

Alternatif olarak, bir astar yerine bir uzantı yöntemi kullanın:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

Kullanımı:

Color colorEnum = "Red".ToEnum<Color>();

VEYA

string color = "Red";
var colorEnum = color.ToEnum<Color>();

7
Kullanıcı girişini işlemek için, karşılaştırmanın büyük / küçük harfe duyarlı OLMADIĞINI (yani "kırmızı" (küçük harf) yazan bir kullanıcı bu değişiklik olmadan yukarıdaki kodu kilitleyeceğini belirtmenize izin veren Enum.Parse aşırı yüklenmesini çağırmak iyi bir fikirdir) .)
BrainSlugs83

9
Kullanışlı, ama soru özellikle ints hakkında soruyor.
BJury

2
bu, dize bir tamsayı ise de işe yarar, örneğin "2"
TruthOf42

2
EnumString boşsa (dün benzer bir sorunu vardı) bu bir istisna atar. Ayrıştırma yerine TryParse kullanmayı düşünün. TryParse ayrıca T'nin bir Enum Tipi olup olmadığını da kontrol edecektir
Justin

Bu tür bir uzatma yöntemi System.Stringad alanı kirliliği gibi görünüyor
Bay Anderson

160

Ben tam bir cevap almak düşünüyorum, insanlar enum .NET içinde dahili olarak nasıl çalıştığını bilmek zorunda.

Şeyler nasıl çalışır

.NET'teki bir numaralandırma, bir değer kümesini (alanları) temel bir türe (varsayılan değer int) eşleyen bir yapıdır . Ancak, enum'unuzun eşlediği integral türünü gerçekten seçebilirsiniz:

public enum Foo : short

Bu durumda, numaralandırma shortveri türüyle eşleştirilir , yani bellekte kısa olarak saklanacak ve yayınladığınızda ve kullandığınızda kısa olarak davranacaktır.

Bir IL açısından bakarsanız, (normal, int) bir enum şöyle görünür:

.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__
}

Burada dikkatinizi çeken şey value__, enum değerlerinden ayrı olarak saklanmasıdır. FooYukarıdaki numaralandırma durumunda , türü value__int16'dır. Bu, temel olarak, türler eşleştiği sürece , bir numarada istediğiniz her şeyi depolayabileceğiniz anlamına gelir .

Bu noktada System.Enum, bir değer türü olduğunu belirtmek isterim , bu temelde BarFlagbellekte 4 bayt Fooalacak ve 2 alacak - örneğin altta yatan türün boyutu (aslında bundan daha karmaşıktır, ancak Hey...).

Cevap

Bu nedenle, bir numaralandırmaya eşlemek istediğiniz bir tamsayı varsa, çalışma zamanının yalnızca 2 şey yapması gerekir: 4 baytı kopyalayın ve başka bir ad verin (numaralandırmanın adı). Veriler değer türü olarak saklandığından kopyalama örtüktür - bu, temel olarak yönetilmeyen kod kullanırsanız, enum ve tam sayıları veri kopyalamadan değiştirebileceğiniz anlamına gelir.

Güvenli hale getirmek için , altta yatan türlerin aynı veya dolaylı olarak dönüştürülebilir olduğunu bilmek ve enum değerlerinin var olmasını sağlamak için en iyi uygulama olduğunu düşünüyorum (varsayılan olarak kontrol edilmez!).

Bunun nasıl çalıştığını görmek için aşağıdaki kodu deneyin:

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

Dökümün e2de işe yaradığını unutmayın! Bu markaları anlamda yukarıdaki derleyici açısından bakıldığında: value__Alan basitçe ya 5 ya da 6 ve dolu Console.WriteLinearamaların ToString(), adı e1ismi olurken çözülene e2değildir.

İstediğiniz bu değilse, kullandığınız Enum.IsDefined(typeof(MyEnum), 6)değerin tanımlı bir numaraya eşlenip eşlenmediğini kontrol etmek için kullanın .

Derleyici aslında bu kontrol olsa da, enum altta yatan türü hakkında açık olduğumu unutmayın. Bunu, yolda sürprizlerle karşılaşmamam için yapıyorum. Bu sürprizleri görmek için aşağıdaki kodu kullanabilirsiniz (aslında bunun veritabanı kodunda çok olduğunu gördüm):

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
Bu eski bir yazı olduğunu fark, ama nasıl c # bilgi düzeyi kazanmak? Bu C # belirtimi okumaktan mı?
Rolan

20
@Rolan Bazen daha fazla insanın bunu sormasını isterdim. :-) Dürüst olmak gerekirse gerçekten bilmiyorum; İşlerin nasıl yürüdüğünü anlamaya ve nereden alabilirsem bilgi edinmeye çalışıyorum. C # standardını okudum, ancak düzenli olarak kodu Reflektör ile de koda ediyorum (hatta x86 montajcı koduna çok bakıyorum) ve tonlarca küçük deney yapıyorum. Ayrıca, diğer dilleri bilmek bu durumda yardımcı olur; Yaklaşık 30 yıldır CS yapıyorum ve bir noktada bazı şeyler 'mantıklı' hale geliyor - f.ex. bir enum ayrılmaz tipte olmalıdır, çünkü aksi takdirde birlikte çalışma bozulur (veya performansınız boşa gider).
atlaste

9
Yazılım mühendisliğini doğru yapmanın anahtarının işlerin nasıl çalıştığını bilmek olduğuna inanıyorum. Benim için bu, bir kod parçası yazarsanız, kabaca f.ex'e nasıl tercüme edildiğini bildiğiniz anlamına gelir. işlemci işlemleri ve bellek getirme / yazma. Bu seviyeye nasıl ulaşacağınızı sorarsanız, bir ton küçük test senaryosu oluşturmanızı, gittikçe daha sert hale getirmenizi, her seferinde sonucu tahmin etmeyi deneyin ve daha sonra bunları test edin (ayrıştırma vb.). Tüm detayları ve tüm özellikleri anladıktan sonra, doğru (donuk) standartta olup olmadığını kontrol edebilirsiniz. En azından benim yaklaşımım bu olurdu.
atlaste

1
Harika cevap, teşekkürler! Son kod örneğinizde, o bir nesne olduğu için çalışma zamanında bir istisna atar. İnt değişkenini, kısa menzil içinde kaldığı sürece kısa devre yapabilirsiniz.
gravidThoughts

@gravidThoughts Teşekkürler. Aslında bu bir kutudan çıkarma işlemidir, bu nedenle tarif ettikleriniz gibi örtük dönüşümler yapmaz. Ayrıntıları bilmiyorsanız C # 'da döküm bazen kafa karıştırıcıdır ... Her neyse, çünkü int! = short, Fırlatacak (kutudan çıkarma başarısız). Eğer yaparsanız object o = (short)5;, işe yarayacak, çünkü o zaman türler eşleşecek. Menzil hakkında değil, gerçekten tür hakkında.
atlaste


64

Bu kod parçasını benim numaralandırma int döküm için kullanıyorum:

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

Bunu en iyi çözüm olarak görüyorum.


1
bu iyi. int destekli bir numaralandırma için geçersiz bir değer verirken bir istisna olmadığını şaşırdı.
orion elenzil

Bu aslında en çok puan alan cevaptan çok farklı değil. Bu yanıt, dizeyi Enum türüne verdikten sonra Enum.IsDefined kullanımını da açıklar. Dize hatasız olarak yayınlansa bile, Enum.IsDefined hala onu yakalayacak
Don Cheadle

53

Aşağıda Enums için güzel bir yardımcı program sınıfı

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

Sayısal değerler için, ne olursa olsun bir nesneyi döndüreceği için bu daha güvenlidir:

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

Bayraklar numaralandırma için çalışmıyor
Seyed Morteza Mousavi


35

Bit maskesi olarak işlev gören ve [Bayraklar] numaralamasında bir veya daha fazla değeri temsil edebilecek bir tamsayı varsa, tek tek bayrak değerlerini bir listede ayrıştırmak için bu kodu kullanabilirsiniz:

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

Bunun altında yatan türün enumişaretli bir 32 bit tam sayı olduğunu varsayarız . Farklı bir sayısal tür olsaydı, kodlanmış 32'yi bu türdeki bitleri yansıtacak şekilde değiştirmelisiniz (veya bunu kullanarak programlı olarak türetmelisiniz Enum.GetUnderlyingType())


1
Bu döngü asla sonlandırılmaz mı? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. Başka bir deyişle, değer her zaman 0x80000000 değerinden daha düşük olacaktır, çünkü D31 = 1 bitinden sonra sıfıra taşar. Daha sonra sonsuza kadar 0 kalır, çünkü 0 değerini sola kaydırdığınızda 0
Christian Gingras

Büyük yakalama @christiangingras, teşekkür ederim! Bunun cevabını değiştirmek için değiştirdim ve en yüksek bit ayarlandığında (yani 0x80000000 / Int32.MinValue) dikkate alınmalıdır
Evan M

27

Bazen bu tür bir nesneniz olabilir MyEnum. Sevmek

var MyEnumType = typeof(MyEnumType);

Sonra:

Enum.ToObject(typeof(MyEnum), 3)

26

Bu bir bayrak numaralandırma farkında güvenli dönüştürme yöntemi:

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
Bu, Enumbunun yerine C # 7.3 ile geliştirilebilir struct, yani çalışma zamanı kontrolüne güvenmemiz gerekmez!
Scott

20

resim açıklamasını buraya girin

Bir dizeyi ENUM veya int yerine ENUM sabitine dönüştürmek için Enum.Parse işlevini kullanmamız gerekir. İşte bir youtube video https://www.youtube.com/watch?v=4nhx4VwdRDk aslında dize ile gösterir ve aynı int için geçerlidir.

Kod aşağıda gösterildiği gibi gider, burada "kırmızı" dizgidir ve "MyColors" renk sabitlerine sahip ENUM rengidir.

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

20

Biraz uzakta asıl soruya aldığım ama bulundu yığın taşması soru bir cevap enum Al int değeri yararlıdır. public const intİlgili intsabitleri bir araya getirmenize ve ardından bunları intkullanırken bunları kullanmanıza gerek kalmadan özelliklere sahip statik bir sınıf oluşturun .

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

Açıkçası, enum tipi işlevlerinden bazıları kaybolacak, ancak bir dizi veritabanı kimliği sabitini saklamak için oldukça düzenli bir çözüm gibi görünüyor.


5
enums, daha fazla tür güvenliği sağladıkları için böyle bir tamsayı sabitinin yerini aldı
Paul Richards

1
Paul, bu, ilgili int sabitlerini (örn. Database id sabitleri) bir araya getirme yöntemidir, böylece her kullanıldıklarında int'e dönüştürülmeden doğrudan kullanılabilirler. Onların tipi ise , değil örneğin DatabaseIdsEnum tamsayı.
Ted

1
Enum tipi güvenliğin istemeden atlanabileceği en az bir durum var.
Thierry

Ancak numaralandırmalar da değerlerin benzersiz olduğundan emin olun, bu yaklaşımın da eksik olduğu bir şey
derHugo

15

Bu, yukarıdaki Tawani yardımcı program sınıfındaki gibi jenerikler kullanarak dot.NET 4.0'da kısmi eşleme ile tamsayıları veya dizeleri bir hedef numaraya ayrıştırır. Ben eksik olabilir komut satırı anahtarı değişkenleri dönüştürmek için kullanıyorum. Bir numaralandırma boş olamayacağından, mantıksal olarak varsayılan bir değer sağlamalısınız. Bu şekilde çağrılabilir:

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

İşte kod:

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: Soru, söz konusu hiç kimsenin Enum.TryParse () içinde de açıkça dönüşmeyeceği tamsayılarla ilgiliydi.


13

Bir dizeden: (Enum.Parse güncel değil, Enum.TryParse öğesini kullanın)

enum Importance
{}

Importance importance;

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

4
Soru özellikle tamsayıları soruyor.
BJury

4
Will Yu herkesi (Dayanamadım) Enum.TryParse enum değeri veya adının bir dizi üzerinde çalışacak bildirmek için düzenlemek cevabınızı lütfen
JeremyWeir

1
Jeremy, Weir bunun üzerinde çalışıyor (karşı koyamadı).
huysentruitw

11

Aşağıdaki biraz daha iyi genişletme yöntemidir

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

Benim durumumda, bir WCF hizmetinden numaralandırma dönmek gerekiyordu. Ayrıca sadece enum.ToString () değil, kolay bir isme ihtiyacım vardı.

İşte benim WCF Sınıfım.

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

İşte Enum'dan Açıklama alan Extension yöntemi.

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

Uygulama:

return EnumMember.ConvertToList<YourType>();

9

Artık bu numaralandırma uzantısının bir parçasını nereden aldığımı bilmiyorum, ancak stackoverflow'dan. Bunun için üzgünüm! Ama bunu aldım ve Bayraklı numaralandırmalar için değiştirdim. Bayraklı numaralandırmalar için bunu yaptım:

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

Misal:

[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

Daha sağlam olmak için bir tür eşleştirme gevşemesi yapmalısınız.

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

Test durumu

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

Bu güzel bir cevap. Şu anda sayfanın altında bir utanç!
MikeBeaton

8

Döküm için farklı yolları ve gelen 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

Herhangi bir giriş verisini kullanıcının istediği numaraya dönüştürmenize yardımcı olabilir . Diyelim ki varsayılan olarak int . Lütfen numaralandırmanızın başına bir Varsayılan değer ekleyin . Girdi değeri ile eşleşme bulunmadığında yardımcılarda kullanılır.

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

Not: Burada enum varsayılan olarak int çünkü değer içine ayrıştırmak çalışıyorum Eğer bayt türü olan bu gibi numaralandırma tanımlarsanız .

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

Yardımcı yöntemde ayrışmayı şu yöntemle değiştirmeniz gerekir:

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

için

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

Aşağıdaki girişler için yöntemimi kontrol ediyorum

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

İngilizcem için üzgünüm


8

İşte atmalarını bir uzantısı yöntemidir Int32için Enum.

Değer mümkün olan en yüksek değerden daha yüksek olsa bile bitsel bayrakları onurlandırır. Örneğin , 1 , 2 ve 4 olasılıkları olan bir enumunuz varsa , ancak int 9 ise , 8'in yokluğunda 1 olarak anlar . Bu, kod güncellemelerinden önce veri güncellemeleri yapmanızı sağlar.

   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

c # numaralandırma bir int döküm için kolay ve net yolu:

 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

Sadece intum enum için açık dönüşüm Cast veya int enum

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

Sadece aşağıdaki gibi yapın:

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

Yalnızca doğru değerleri verdiğinizden ve bunun dışında bir istisna atabildiğinizden emin olmak için:

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

IsDefined'i kullanmanın maliyetli ve hatta dökümden daha fazlası olduğunu unutmayın, bu yüzden onu kullanmaya karar vermeniz uygulamanıza bağlıdır.


3

Uzantı yöntemini kullanabilirsiniz.

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

feryat kodu gibi kullan

Sıralama :

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

Kullanımı:

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
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.