Эй все, получил быстрый вопрос, о котором я, может казаться, ничего не нахожу...
Я работаю над проектом, который требует перечислений флага с большим количеством флагов (до с 40 выходами), и я действительно не испытываю желание вводить в точной маске для каждой перечислимой величины:
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
}
Кроме того, я также надеюсь, что существует легкое (множитель) способ для меня управлять фактической договоренностью битов на различных машинах порядка байтов, так как эти значения будут в конечном счете сериализированы по сети:
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
}
Просто удивление, если у кого-либо есть какие-либо классные идеи, Спасибо!
Вы можете написать шаблон 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, например этот (это дает вам подсветку синтаксиса и Intellisense)
Ну, для решения проблемы 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 не является проблемой, но, конечно, есть и другие недостатки, такие как размер полезной нагрузки и общая производительность.
Почему бы просто не сделать:
public enum MyEnumeration : ulong
{
Flag1 = 1,
Flag2 = 1 << 1,
Flag3 = 1 << 2,
Flag4 = 1 << 3,
.
.
.
Flag30 = 1 << 29,
Flag31 = 1 << 30,
Flag32 = 1 << 31
}