Soru C # ile enine int için cast


Nasıl olabilir int bir yere dökülmek enum C # içinde?


2571
2017-08-27 03:58


Menşei


Diğer yol boyunca: get-int-değer-den-enum - nawfal
Aşağıdaki cevapların en iyilerini kapsayan ücretsiz 5 dakikalık video: app.deviq.com/courses/how-do-i-convert-int-to-enum-in-c-sharp - ssmith


Cevaplar:


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üncelleştirme:

Sayısından da yapabilirsiniz

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

3123
2017-08-27 03:59



@FlySwat, ya eğer YourEnum dinamiktir ve sadece çalışma zamanında bilinir ve benim istediğim şey Enum? - Shimmy
Kodunuzun gizlenmesi durumunda Enum.Parse'ın çalışmadığını unutmayın. Obfüsasyondan sonraki çalışma zamanında dize enum isimleri ile karşılaştırılır ve bu noktada enumların isimleri onların olmasını beklediğiniz gibi değildir. Çözümlemeniz, sonuç olarak daha önce başarılı oldukları yerde başarısız olur. - jropella
DİKKAT Yukarıdaki "bir dizgeden" sözdizimini kullanırsanız ve bir sayı olan geçersiz bir dizgeyi (ör. "2342342") girerseniz - bu, enum değerinizin bir değeri olmadığı varsayılırsa), bir hata atmadan buna izin verir! Sayınız, enum içinde geçerli bir seçim olmasa bile bu değere (2342342) sahip olacaktır. - JoeCool
Sanırım bu cevap biraz tarihli. Dize için gerçekten kullanmalısın var result = Enum.TryParse(yourString, out yourEnum) günümüzde (ve dönüşümün başarısız olup olmadığını belirlemek için sonucu kontrol etmek). - Justin T Conroy
Sahip olmak da mümkündür Enum.Parse ekleyerek büyük küçük harf duyarlı true aramaya parametre değeri: YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true); - Erik Schierboom


Sadece yayınla:

MyEnum e = (MyEnum)3;

Kullanarak aralıkta olup olmadığını kontrol edebilirsiniz Enum.IsDefined:

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

721
2017-08-27 04:01



Flags özniteliğini kullanırsanız ve değer bayrakların bir birleşimi ise Enum.IsDefined kullanamazsınız dikkat edin: Keys.L | Keys.Control - dtroy
ilişkin Enum.IsDefined, tehlikeli olabileceğinin farkında olun: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx - adrian
Öte yandan, girişi kütüphanenin sağladığı kütüphaneye göre doğrularsam, kütüphanenin kendisine göndermeden önce ... - Alexander
Bu tanımı tercih ederim: Msgstr "Belirtilen bir değerde bir sabitin sabit olup olmadığını gösteren bir belirtme döndürür" itibaren MSDN - Pap
... Çünkü tanımınız yanıltıcı olabilir, çünkü siz diyorsunuz: "... menzilde olup olmadığını kontrol et ..." başlangıç ​​ve bitiş limitleri ile bir dizi sayı içinde ima eder ... - Pap


Alternatif olarak, bir liner 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>();

198
2017-11-11 13:27



Kullanıcı girişini işlemek için, muhtemelen Enum.Parse'nin aşırı yüklenmesini çağırmak iyi bir fikirdir. Bu, karşılaştırmanın büyük / küçük harfe duyarlı OLMADIĞINI (örn. "Kırmızı" (küçük harf) yazılan bir kullanıcının bu kodu değiştirmeden yukarıdaki kodu bozacağını belirtmenize izin verir. .) - BrainSlugs83
Cool, bunun dışında bir soru değil. - nawfal
Handy, ama soru özellikle ints hakkında sorar. - BJury
Bu ayrıca, dizgi bir tam sayı ise, örneğin, "2" - TruthOf42
EnumString boşsa (bu, dün benzer bir sorunu vardı), bu bir istisna atar. Ayrıştırma yerine TryParse'ı kullanmayı düşünün. TryParse, T'nin bir Enum Türü olup olmadığını da kontrol edecektir - Justin


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

İşler nasıl çalışır

.NET'teki bir enum, bir değerler kümesini (alanları) temel bir türle eşleyen bir yapıdır (varsayılan değer). int). Bununla birlikte, enum'inizle eşleştiği ayrılmaz türü seçebilirsiniz:

public enum Foo : short

Bu durumda enum, short veri tipi, yani bellekte kısa olarak saklanacak ve onu kullanırken ve kullandığınızda kısa olarak davranacaktır.

Eğer bir IL bakış açısından bakarsanız, bir (normal, int) 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 depolanır. Enum durumunda Foo yukarıda, türü value__ int16. Bu temel olarak, bir numarada istediğiniz her şeyi saklayabileceğiniz anlamına gelir. türler eşleştiği sürece.

Bu noktada şunu belirtmek isterim System.Enum temel olarak bunu ifade eden bir değer türüdür BarFlag bellekte 4 bayt alacak ve Foo 2'yi alacaktır - ör. Altta yatan türün boyutu (aslında bundan daha karmaşıktır, ama hey ...).

Cevap

Dolayısıyla, bir enum ile eşleştirmek istediğiniz bir tamsayıya sahipseniz, çalışma zamanı yalnızca 2 şey yapmalıdır: 4 bayt kopyalayın ve ona başka bir ad verin (enum'un adı). Veriler, değer türü olarak saklandığından kopyalama işlemi örtülüdür - bu, temel olarak, yönetilmeyen kod kullanırsanız, verileri kopyalamaksızın enum ve tamsayıları birbiriyle eşleştirebileceğiniz anlamına gelir.

Güvenli hale getirmek için bence en iyi uygulama Altta yatan türlerin aynı olduğunu veya örtük olarak dönüştürülebilir olduğunu bilin ve enum değerlerinin varolduğundan emin olmak için (bunlar varsayılan olarak işaretlenmez!).

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üne dikkat edin e2 ayrıca çalışır! Yukarıdaki derleyici perspektifinden bu mantıklıdır: value__ alan sadece 5 veya 6 ile doldurulur ve ne zaman Console.WriteLine aramalar ToString(), adı e1 adı çözülürken e2 değil.

Eğer istediğin buysa, kullan Enum.IsDefined(typeof(MyEnum), 6) Tanımladığınız değer, tanımlı bir enum ile eşleşip eşleşmediğini kontrol etmek için.

Ayrıca, derleyici aslında bunu denetlese bile, enumun temel türü hakkında açık olduğumu unutmayın. Yol boyunca herhangi bir sürprizle karşılaşmamam için bunu yapıyorum. Bu sürprizleri hareket halinde 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();
}

116
2018-04-03 07:39



Bunun eski bir yazı olduğunu anlıyorum ama c # düzeyinde bu bilgi düzeyini nasıl kazanıyorsunuz? Bu C # belirtiminden okuma mı? - Rolan
@Rolan Bazen daha çok insanın bunu sormasını dilerim. :-) Dürüst olmak gerekirse gerçekten bilmiyorum; İşlerin nasıl yürüdüğünü ve nereden bulabildiğimi nereden öğrendiğimi anlamaya çalışıyorum. C # standardını okudum, ama ben de düzenli olarak Reflector (hatta x86 assembler koduna çok bakıyorum) kodunu koda dönüştürüyorum ve tonlarca küçük deney yaparım. Ayrıca, diğer diller hakkında bilmek bu durumda yardımcı olur; Yaklaşık 30 yıldır CS yapıyordum ve bir noktada bazı şeyler 'mantıklı' oluyor - f.ex. bir enum integral türler olmalıdır, çünkü aksi takdirde interop kesintiye uğrayacaktır (ya da performansınız tahliye edilecektir). - atlaste
Yazılım mühendisliğinin doğru yapılmasının anahtarının, işlerin nasıl çalıştığını bildiğine inanıyorum. Benim için bu, bir kod parçası yazarsanız, kabaca f.ex.'ye nasıl dönüştüğünü bilirsiniz. işlemci işlemleri ve bellek getiriyor / yazıyor. Bu seviyeye nasıl ulaşacağınızı sorarsanız, bir ton kadar küçük test vakası inşa etmenizi öneririm, bu da onları gittikçe zorlaştırır, her seferinde sonucu tahmin etmeye çalışır ve sonradan test eder (dekomplasyon, vb.). Tüm detayları ve tüm özellikleri belirledikten sonra, (donuk) standartta sağlayıp sağlamadığınızı kontrol edebilirsiniz. En azından bu benim yaklaşımım olurdu. - atlaste
Fantastik cevap, teşekkürler! Son kod örneğinizde, çalışma zamanında bir istisna atar çünkü o bir nesnedir. Bir int değişkenini kısa menzilde düştüğü sürece kısa bir değere çevirebilirsiniz. - gravidThoughts
@gravidThoughts Teşekkürler. Aslında bu bir çıkarma işlemidir, bu nedenle açıkladığınız gibi gizli dönüşümler yapmayacaktır. Ayrıntıları bilmiyorsan, döküm bazen C # 'da kafa karıştırıcıdır. int ! = short, atıyor (kutuyu açma başarısız). Yaparsan object o = (short)5;Çalışır, çünkü o zaman türler eşleşir. Bu menzil ile ilgili değil, gerçekten tip hakkında. - atlaste


Aşağıdaki örneğe geçin:

int one = 1;
MyEnum e = (MyEnum)one;

89
2017-08-27 04:00





Enumuma int için bu kod parçasını kullanıyorum:

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

En iyi çözümü buluyorum.


54
2017-10-21 10:05



Bayrak enumlarıyla çalışmaz - Daniel Fisher lennybacon
bu iyi. Bir destekli bir enum için geçersiz bir değer verirken bir istisna olmadığını şaşırdım. - orion elenzil
Bu aslında en iyi cevaptan çok farklı değil. Bu yanıt, dizeyi Enum türüne gönderdikten sonra Enum.IsDefined kullanarak da tartışır. Bu nedenle, string hatasız bir şekilde oluşturulmuş olsa bile, Enum.IsDefined yine de onu yakalayacaktır. - mmcrae


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

44
2017-09-07 04:42





4.0 için hazırsan .AĞ Çerçeve, yeni var Enum.TryParse () Çok kullanışlı ve [Bayraklar] özniteliği ile iyi oynadığı işlev. Görmek Enum.TryParse Yöntemi (String, TEnum%)


37
2017-11-01 14:58



Bir dizeden dönüştürürken yararlıdır. Ancak int’den dönüştürülürken değil. - CodesInChaos