2010-01-25 10 views
6

Enums'in C# ile nasıl çalıştığını anlıyorum ve Flags özniteliğinin tabloya getirdiği şeyi elde ediyorum.C# Enums öğelerini [Flags] özelliğiyle tanımlamanın birden fazla yolu var mı?

Bu soruyu gördüm, here. Hangi ilk lezzet önerir, ancak bunun için herhangi bir sebep/gerekçe sağlamaz.

Bu ikisinin tanımlanma biçiminde bir fark var mı, diğerinden daha iyi mi? İlk synax'ı ikinci yerine kullanmanın avantajları nelerdir? Bayraklar Enums yazı tiplerini tanımlarken her zaman ikinci lezzeti kullandım ... bu sefer yanlış mı yapıyorum?

[Serializable] 
[Flags] 
public enum SiteRoles 
{ 
    User = 1 << 0, 
    Admin = 1 << 1, 
    Helpdesk = 1 << 2 
} 

mi değil aynı

[Serializable] 
[Flags] 
public enum SiteRoles 
{ 
    User = 1, 
    Admin = 2, 
    Helpdesk = 4 
} 
+0

Bu 2 kod fragmanı için üretilen IL kodu aynıdır. –

+3

Bu kodda hatayı bulun: BackupOperator = 1073714824. Hata ile ilk etapta BackupOperator = 1 << 30 –

+0

diyebilirim. Tüm bilgi için teşekkürler, çünkü daha iyi görünüyor çünkü ilk yaklaşımını kullanacağım tüm ama en basit durumlar. – Nate

cevap

6

Birincisi ile ana avantaj, derleyici sizin için yapacağından her bayrak için doğru değerleri hesaplamanıza gerek olmamasıdır. Bunun dışında aynıdırlar.

+0

Yani temelde bir derleyici numarası? – Nate

+2

Evet, 1 << n bir sabittir, böylece derleyici 1,2,4,8'den daha az hataya neden olabilecek şekilde hesaplamalıdır ... Ayrıca hex'yi de kullanabilirsiniz. 0x1, 0x10, 0x100 ... – Lee

+1

0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 gibi onaltılık değerlerle daha fazla ilgilenebilirsiniz. –

0

olarak onun AFAIK bir okunabilirliği tartışmanın söyledi. Bazıları birincisi daha okunabilir olduğunu söyler, çünkü '< <' sağ tarafındaki bayrakların gerçek dizinine sahipsiniz.

+0

Bu, derleyici bir hile o zaman etkili mi? 1 << 2 = 4'ten beri mi? – Nate

+1

Bu bir derleyici değil. Helpdesk = 1 << 2, Helpdesk = 4 veya Helpdesk = 3 + 1 arasındaki fark nedir? Sadece değerlendirilen bir ifade. – empi

+0

Sanırım derleyiciden ve dolayısıyla derleyiciden yararlanıyor. Fikrin güzel. – Nate

6

daha karmaşık örnekleri göz önünde bulundurun:

[Flags] 
public enum SiteRoles 
{ 
    User = 1 << 12, 
    Admin = 1 << 13, 
    Helpdesk = 1 << 15, 
    AdvancedUser = User | Helpdesk, //or (1<<12)|(1<<13) 
} 

[Flags] 
public enum SiteRoles 
{ 
    User = 4096, //not so obvious! 
    Admin = 8192, 
    Helpdesk = 16384, 
    AdvancedUser = 12288, //! 
} 

[Flags] 
public enum SiteRoles 
{ 
    User = 0x1000, //we can use hexademical digits 
    Admin = 0x2000, 
    Helpdesk = 0x4000, 
    AdvancedUser = 0x3000, //it much simpler calculate binary operator OR with hexademicals 
} 

Bu numuneler bu durumda ilk sürümde ÇOK DAHA okunabilir olduğunu göstermektedir. Ondalık baskınlar, bayrak sabitlerini temsil etmenin en iyi yolu değildir. Ve bitwise işlemleri hakkında daha fazla bilgi için (bu, bayrak sabitlerini temsil etmek için de kullanılabilir) bkz. http://en.wikipedia.org/wiki/Bitwise_operation

0

Bunu yapmak için başka bir yol daha şıktır ve bu yüzden kısa süre önce yazdığım bir şeyi paylaşacağımı düşündüm. Çok az matematik gerektiren bir yararı vardır ve bu yüzden daha az hata eğilimli olduğunu düşünüyorum. Çok okunabilir, IMHO.

[Flags][Serializable] 
public enum ScopeType : int 
{ 
    Unknown = 0, 
    Global = 1, 
    Namespace = Global << 1, 
    Class = Namespace << 1, 
    Struct = Class << 1, 
    Interface = Struct << 1, 
    Enum = Interface << 1, 
    Function = Enum << 1, 
    Property = Function << 1, 
    PropertyGetter = Property << 1, 
    PropertySetter = PropertyGetter << 1, 
    Using = PropertySetter << 1, 
    If = Using << 1, 
    ElseIf = If << 1, 
    Else = ElseIf << 1, 
    Switch = Else << 1, 
    Case = Switch << 1, 
    For = Case << 1, 
    While = For << 1, 
    DoWhile = While << 1, 
    Lambda = DoWhile << 1, 
    Try = Lambda << 1, 
    Catch = Try << 1, 
    Finally = Catch << 1, 
    Initializer = Finally << 1, 
    Checked = Initializer << 1, 
    Unchecked = Checked << 1, 
    Unsafe = Unchecked << 1, 
    Lock = Unsafe << 1, 
    Fixed = Lock << 1, 

    // I can also group flags together using bitwise-OR. 
    PropertyAccessor = PropertyGetter | PropertySetter, 
    TypeDefinition = Class | Struct | Interface | Enum, 
    TryCatchFinally = Try | Catch | Finally, 
    Conditional = If | ElseIf | Else, 
    Branch = Conditional | Case | TryCatchFinally, 
    Loop = For | While | DoWhile 
} 

NOT: numaralandırma System.Int32 devraldığı beri, sadece 32 bayrakları tanımlayabilirsiniz. Daha fazlasına ihtiyacınız varsa, daha büyük bir tamsayı (System.Int64) kullanmanız, birden fazla numaralandırma oluşturup bunları birleştirmeniz veya yalnızca bir grup boolean değeriyle bir sınıf oluşturmanız gerekir.