2010-05-07 183 views
13

嘿大家,有一個快速的問題,我似乎無法找到任何東西...大標誌枚舉

我工作的一個項目,需要有大量的標誌旗枚舉(高達40-ISH),我真的不覺得自己的確切面具每個枚舉值輸入:

public enum MyEnumeration : ulong 
{ 
    Flag1 = 1, 
    Flag2 = 2, 
    Flag3 = 4, 
    Flag4 = 8, 
    Flag5 = 16, 
    // ... 
    Flag16 = 65536, 
    Flag17 = 65536 * 2, 
    Flag18 = 65536 * 4, 
    Flag19 = 65536 * 8, 
    // ... 
    Flag32 = 65536 * 65536, 
    Flag33 = 65536 * 65536 * 2 
    // right about here I start to get really pissed off 
} 

此外,我也希望有一個簡單的(IER)的方式對我來說以控制不同端機上位的實際排列,因爲這些值最終將通過網絡串行化:

public enum MyEnumeration : uint 
{ 
    Flag1 = 1,  // BIG: 0x00000001, LITTLE:0x01000000 
    Flag2 = 2,  // BIG: 0x00000002, LITTLE:0x02000000 
    Flag3 = 4,  // BIG: 0x00000004, LITTLE:0x03000000 
    // ... 
    Flag9 = 256, // BIG: 0x00000010, LITTLE:0x10000000 
    Flag10 = 512, // BIG: 0x00000011, LITTLE:0x11000000 
    Flag11 = 1024 // BIG: 0x00000012, LITTLE:0x12000000 
} 

所以,我有種想知道是否有一些冷靜的方式來設置我的枚舉像:

public enum MyEnumeration : uint 
{ 
    Flag1 = flag(1), // BOTH: 0x80000000 
    Flag2 = flag(2), // BOTH: 0x40000000 
    Flag3 = flag(3), // BOTH: 0x20000000 
    // ... 
    Flag9 = flag(9), // BOTH: 0x00800000 
} 

我已經試過:

// this won't work because Math.Pow returns double 
// and because C# requires constants for enum values 
public enum MyEnumeration : uint 
{ 
    Flag1 = Math.Pow(2, 0), 
    Flag2 = Math.Pow(2, 1) 
} 

// this won't work because C# requires constants for enum values 
public enum MyEnumeration : uint 
{ 
    Flag1 = Masks.MyCustomerBitmaskGeneratingFunction(0) 
} 

// this is my best solution so far, but is definitely 
// quite clunkie 
public struct EnumWrapper<TEnum> where TEnum 
{ 
    private BitVector32 vector; 
    public bool this[TEnum index] 
    { 
     // returns whether the index-th bit is set in vector 
    } 
    // all sorts of overriding using TEnum as args 
} 

剛想知道如果有人有任何很酷的想法,謝謝!

+3

您輸入幾百行文字在這裏。你爲什麼不咬一口就打出原來的40行? (你可能已經使用了1 << 1,1 << 2,...而不是乘法,但是無論如何...) – 2010-05-07 22:45:24

+0

嗯......我確實想提出我曾試過的解決方案,「<<" and ">>」會有工作,但當他們只被評估一次時,我不會完全看到差異。它不需要花費我半個小時才能輸出,幾百行文字並不多...我寧願提供太多的信息,也不能太少... – LorenVS 2010-05-07 22:51:42

+1

您可以使用全變量運算符的ulong,您只需向編譯器指出您正在轉換的是一個ulong。 1ul << 63,注意'ul'的1. – 2010-05-07 23:09:19

回答

9

你可以寫一個T4模板來生成枚舉:

模板(MyEnumeration.tt)

<#@ template language="C#" #> 
<#@ output extension=".cs" #> 
using System; 

namespace MyNamespace 
{ 
    [Flags] 
    public enum MyEnumeration : ulong 
    { 
<# 
    ulong value = 1; 
    for(int i = 1; i <= 64; i++) 
    { 
#> 
     Flag<#= i #> = <#= string.Format("0x{0:X8}", value) #>, 
<# 
     value = value << 1; 
    } 
#> 
    } 
} 

得到的C#代碼(MyEnumeration.cs)

using System; 

namespace MyNamespace 
{ 
    [Flags] 
    public enum MyEnumeration : ulong 
    { 
     Flag1 = 0x00000001, 
     Flag2 = 0x00000002, 
     Flag3 = 0x00000004, 
     Flag4 = 0x00000008, 
     Flag5 = 0x00000010, 
     Flag6 = 0x00000020, 
     Flag7 = 0x00000040, 
     Flag8 = 0x00000080, 
     Flag9 = 0x00000100, 
     Flag10 = 0x00000200, 
     Flag11 = 0x00000400, 
     Flag12 = 0x00000800, 
     Flag13 = 0x00001000, 
     Flag14 = 0x00002000, 
     Flag15 = 0x00004000, 
     Flag16 = 0x00008000, 
     Flag17 = 0x00010000, 
     Flag18 = 0x00020000, 
     Flag19 = 0x00040000, 
     Flag20 = 0x00080000, 
     Flag21 = 0x00100000, 
     Flag22 = 0x00200000, 
     Flag23 = 0x00400000, 
     Flag24 = 0x00800000, 
     Flag25 = 0x01000000, 
     Flag26 = 0x02000000, 
     Flag27 = 0x04000000, 
     Flag28 = 0x08000000, 
     Flag29 = 0x10000000, 
     Flag30 = 0x20000000, 
     Flag31 = 0x40000000, 
     Flag32 = 0x80000000, 
     Flag33 = 0x100000000, 
     Flag34 = 0x200000000, 
     Flag35 = 0x400000000, 
     Flag36 = 0x800000000, 
     Flag37 = 0x1000000000, 
     Flag38 = 0x2000000000, 
     Flag39 = 0x4000000000, 
     Flag40 = 0x8000000000, 
     Flag41 = 0x10000000000, 
     Flag42 = 0x20000000000, 
     Flag43 = 0x40000000000, 
     Flag44 = 0x80000000000, 
     Flag45 = 0x100000000000, 
     Flag46 = 0x200000000000, 
     Flag47 = 0x400000000000, 
     Flag48 = 0x800000000000, 
     Flag49 = 0x1000000000000, 
     Flag50 = 0x2000000000000, 
     Flag51 = 0x4000000000000, 
     Flag52 = 0x8000000000000, 
     Flag53 = 0x10000000000000, 
     Flag54 = 0x20000000000000, 
     Flag55 = 0x40000000000000, 
     Flag56 = 0x80000000000000, 
     Flag57 = 0x100000000000000, 
     Flag58 = 0x200000000000000, 
     Flag59 = 0x400000000000000, 
     Flag60 = 0x800000000000000, 
     Flag61 = 0x1000000000000000, 
     Flag62 = 0x2000000000000000, 
     Flag63 = 0x4000000000000000, 
     Flag64 = 0x8000000000000000, 
    } 
} 

爲了編輯T4模板,我建議你使用一個T4編輯器插件像this one(此爲您提供了語法高亮和智能感知)

+0

您幾乎不需要T4系統就可以做到這一點。任何腳本編程語言中的簡單循環都可以打印此核心。 – 2010-05-08 04:08:14

+0

是的,但T4內置於Visual Studio中,這使得它對於那種事情非常方便... – 2010-05-08 15:23:37

+0

不錯。是否有可能超過64? – arao6 2014-10-02 23:53:11

0

好解決endianes你有,我能想到的把我的頭

1-處理序列化你的自我和使用System.Net.IPAddress.HostToNetworkOrder的頂部有兩個選項,以確保一致的字節順序上當你反序列化的時候,連線和System.Net.IPAddress.NetworkToHostOrder相反。

我有兩個關於二進制序列化的舊博客文章,他們可以做一個更新,但它是一個起點。

http://taylorza.blogspot.com/2010/04/archive-binary-data-from-structure.html
http://taylorza.blogspot.com/2010/04/archive-structure-from-binary-data.html

2-序列化到XML,在這種情況下endianes不是一個問題,但當然也有其他缺點,例如有效載荷大小和一般性能。

9

爲什麼不只是做:

public enum MyEnumeration : ulong 
{ 
    Flag1 = 1, 
    Flag2 = 1 << 1, 
    Flag3 = 1 << 2, 
    Flag4 = 1 << 3, 
    . 
    . 
    . 
    Flag30 = 1 << 29, 
    Flag31 = 1 << 30, 
    Flag32 = 1 << 31 
} 
+0

嗯...位8位後面的位移似乎對我來說很奇怪......我不確定編譯器是否自動處理這個問題,但從技術上講,不應該1 << 8)== 0,無論小端系統上的數據類型的大小如何?我可能會完全外出吃午飯,我不確定 – LorenVS 2010-05-07 22:55:03

+7

@LorenVS,你可以用移位操作符來使用ulong的全部範圍,你只需要向編譯器指出你正在移動的1是一個ulong。 1ul << 63,注意'ul'是1. – 2010-05-07 23:10:06

+3

@LorenVS - 編譯器沒有問題。但是,它被封裝成數據大小。所以實際上對於'int' /'Int32'來說,1 << 33與1 << 1是一樣的。既然(注意Chris的評論,但是)在這種情況下我們使用的是'ulong',所以它是%64,所以1 < <65與1相同<< 1 – 2010-05-07 23:10:55