2011-02-11 12 views
10

en bu enum var diyelim: Ben sadece can ilk enum değerler arasındanasıl karmaşık sıralama değeri dize temsilini almak için

SomeType easyType = SomeType.Val1 | SomeType.Val2; 
SomeType complexType = SomeType.All; 

Ben döngü isterseniz:

[Flags] 
public enum SomeType 
{  
    Val1 = 0, 
    Val2 = 1, 
    Val3 = 2, 
    Val4 = 4, 
    Val5 = 8, 
    Val6 = 16, 
    All = Val1 | Val2 | Val3 | Val4 | Val5 | Val6 
} 

ve bazı değişkenler yapın:

foreach(string s in easyType.ToString().Split(',')) 
{ ... } 

Ancak, elbette 'complexType' ı değeri elde 'Tümü', aynı yaklaşımı uygulamaya çalışırken Geçerli, aynı zamanda, enum'un olası değerlerinden biridir. Ancak, SomeType.All'ın hangi değerlerden oluştuğunu görmek için net bir yol var mı? Ben böyle tüm değerleri üzerinden manuel döngü yapabilir biliyorum:

if(complexType.HasFlag(ManualType.Val1) && ... 
+0

Sorunun bu enum içine 'All' koymak gerektiğini düşünüyorum neden örneğin, bir That. Bunu [Flags] 'olarak işaretlediğinizden, içinde herhangi bir kombinasyon koymak kötü bir fikirdir. –

+0

O zamanlar (ve diğerleri) bir şey için SomeType kullanırken her zaman enumların düzgün kombinasyonunu kullanmayı hatırlamak zorunda kalacaklar. – IamDeveloper

+0

Orijinal enum'u anlamsız 'SomeType' yerine gönderebilir misiniz? –

cevap

4
var result = string.Join(",", 
       Enum.GetValues(typeof(SomeType)) 
        .Cast<SomeType>() 
        .Where(v => complexType.HasFlag(v))); 

kendini tekrar etmekten kaçınmanın yolu.

+1

Bu, sonunda ", Tümü" de dahil olmaz mı? Bunu görmezden gelmek için özel bir davaya gerek var mı? – Justin

+0

@Justin: Evet olacak. Ama ne yapabiliriz? "Hepsi" olup olmadığını kontrol et. Ya adı "AllOptions" ise? Bu yüzden bu "özel durum" ile baş edemeyiz. –

+0

Düşünebildiğim tek seçenek, görülen tüm önceki değerlerin bitwise-OR'sini devam ettirmek ve herhangi bir yeni bit içermemesi durumunda bir değeri göz ardı etmektir. Yine de, emre bağımlı olacaktır. – Justin

0

Belki enum değerleri numaralandırmak ve test etmemiz gerekiyor her biri: Sen bir uzantı yazabilirsiniz

foreach (SomeType item in Enum.GetValues (typeof (SomeType)) 
{ 
    if ((complexType & item) == item) 
    { 
    //... 
    } 
} 
+0

Ama sonra da Hepsi için test edeceğim. Bu benim durumumda tamam, ama ne de tanımlamış olsaydım, eğer SomeType.JustThree = Val1 | Val2 | Val3. En azından gereksiz. – IamDeveloper

0

Burada, bunu yapmak için bir olası yolu Danny Chen'in yanıta bina:

public IEnumerable<T> GetFlags<T>(Predicate<int> hasFlag) 
{ 
    return GetEnumFlags<T>().Where(f => hasFlag(f)).Cast<T>(); 
} 

private IEnumerable<int> GetEnumFlags<T>() 
{ 
    return Enum.GetValues(typeof(T)).Cast<int>().Where(IsPowerOfTwoOrZero); 
} 

private bool IsPowerOfTwoOrZero(int v) 
{ 
    return ((v & (v-1)) == 0); 
} 

Kullanımı: Bu int için dökülebilir türlerine göre numaralamalar için çalışacak

void Main() 
{ 
    SomeType easyType = SomeType.Val1 | SomeType.Val2; 
    SomeType complexType = SomeType.All; 

    GetFlags<SomeType>(v => easyType.HasFlag((SomeType)v)); 
    GetFlags<SomeType>(v => complexType.HasFlag((SomeType)v)); 
} 

Not. long vb. Için benzer yöntemler oluşturabilirsiniz.

0

Daha derin bir karmaşıklık düzeyine sahip verilerin (rastgele öğe grupları, "karanlığın" vb.) Temsil edilmesi ve bunun yüzünden mücadele etmek için bir enum kullanıyorsanız , Bir enum'un kullanmak için yanlış programlama yapısı olduğunu öneriyorum.

Bu görevler için bir enum kullanmak her zaman yanıltıcı olacaktır: Enuminize yeni bir renk eklerseniz, onu da "Parlak" veya "Koyu" olarak eklemeyi unutmayın. Bu, kodunuzu geliştiriciler için orijinal sorun olarak yanıltıcı bir hata yapar. Ne ne, class veya struct, parlak olup olmadığını belirten bir özelliği olan renk için tanımlayabilirsiniz. Daha sonra, daha basit bir dil özelliğini kötüye kullanmaya çalıştığınız zamanki gibi yanlış sonuçlar vermeyecek şekilde uygulanmış, anlaşılır, anlaşılabilir bir işlevsellik elde edersiniz.

Color is a struct ...

İlgili konular