2010-05-07 120 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