我有以下枚举
[Flags]
internal enum DataSectionFlags : uint
{
TypeReg = 0x0,
TypeDsect = 0x01,
TypeNoLoad = 0x02,
TypeGroup = 0x04,
TypeNoPadded = 0x08,
TypeCopy = 0x010,
ContentCode = 0x020,
ContentInitializedData = 0x040,
ContentUninitializedData = 0x080,
LinkOther = 0x0100,
LinkInfo = 0x0200,
TypeOver = 0x0400,
LinkRemove = 0x0800,
LinkComDat = 0x01000,
NoDeferSpecExceptions = 0x04000,
RelativeGP = 0x08000,
MemPurgeable = 0x020000,
Memory16Bit = 0x020000,
MemoryLocked = 0x040000,
MemoryPreload = 0x080000,
Align1Bytes = 0x0100000,
Align2Bytes = 0x0200000,
Align4Bytes = 0x0300000,
Align8Bytes = 0x0400000,
Align16Bytes = 0x0500000,
Align32Bytes = 0x0600000,
Align64Bytes = 0x0700000,
Align128Bytes = 0x0800000,
Align256Bytes = 0x0900000,
Align512Bytes = 0x0A00000,
Align1024Bytes = 0x0B00000,
Align2048Bytes = 0x0C00000,
Align4096Bytes = 0x0D00000,
Align8192Bytes = 0x0E00000,
LinkExtendedRelocationOverflow = 0x01000000,
MemoryDiscardable = 0x02000000,
MemoryNotCached = 0x04000000,
MemoryNotPaged = 0x08000000,
MemoryShared = 0x10000000,
MemoryExecute = 0x20000000,
MemoryRead = 0x40000000,
MemoryWrite = 0x80000000
}
我正在像这样用这个枚举强制转换uint变量
var testVariable = (DataSectionFlags) 1610612768;
我有一个像上面这样处理上述变量的方法
private static uint GetSectionProtection(DataSectionFlags characteristics)
{
uint result = 0;
if (characteristics.HasFlag(DataSectionFlags.MemoryNotCached))
{
// PageNoCache
result |= 0x200;
}
if (characteristics.HasFlag(DataSectionFlags.MemoryExecute))
{
if (characteristics.HasFlag(DataSectionFlags.MemoryRead))
{
if (characteristics.HasFlag(DataSectionFlags.MemoryWrite))
{
// PageExecuteReadWrite
result |= 0x40;
}
else
{
// PageExecuteRead
result |= 0x20;
}
}
else if (characteristics.HasFlag(DataSectionFlags.MemoryWrite))
{
// PageExecuteWriteCopy
result |= 0x80;
}
else
{
// PageExecute
result |= 0x10;
}
}
else if (characteristics.HasFlag(DataSectionFlags.MemoryRead))
{
if (characteristics.HasFlag(DataSectionFlags.MemoryWrite))
{
// PageReadWrite
result |= 0x04;
}
else
{
// PageReadOnly
result |= 0x02;
}
}
else if (characteristics.HasFlag(DataSectionFlags.MemoryWrite))
{
// PageWriteCopy
result |= 0x08;
}
else
{
// PageNoAccess
result |= 0x01;
}
return result;
}
我正在尝试简化此方法中的长条条件语句,但是这样做很麻烦。
在保持其功能的同时在方法内部编写条件语句的最简单方法是什么?
答案 0 :(得分:4)
我建议使用类似以下的查找字典:
var sectionProtection = new Dictionary<DataSectionFlags, uint>
{
[DataSectionFlags.TypeReg ] = 1,
[DataSectionFlags.TypeDsect ] = 2,
...
[DataSectionFlags.MemoryExecute | DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite] = 0x40,
...
};
请注意,每种标志组合都需要一个单独的条目。在这种情况下,您可以使用以下语句替换函数
var testVariable = sectionProtection[(DataSectionFlags) 1610612768];
,或者,如果没有定义每个组合,则:
if (sectionProtection.TryGetValue((DataSectionFlags) 1610612768, out testVariable ))
我认为这不仅更易于理解,运行更快,而且更正确。在创建if ... else if ... else if ...
语句列表时,很容易错过组合,使相同的组合返回不同的值或两次包含相同的组合。如果您错过了查询字典中的组合,则会得到一个异常(或TryGetValue
返回false
)。如果将相同的组合两次添加到字典中,则会出现错误。
答案 1 :(得分:1)
这是我能在短时间内提出的最佳建议:
private static uint GetSectionProtection(DataSectionFlags characteristics)
{
uint result = 0;
if (characteristics.HasFlag(DataSectionFlags.MemoryNotCached))
{
// PageNoCache
result |= 0x200;
}
var ladder = new KeyValuePair<DataSectionFlags[], uint>[]
{
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryExecute, DataSectionFlags.MemoryRead, DataSectionFlags.MemoryWrite, }, 0x40),
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryExecute, DataSectionFlags.MemoryRead, }, 0x20),
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryExecute, DataSectionFlags.MemoryWrite, }, 0x80),
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryExecute, }, 0x10),
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryRead, DataSectionFlags.MemoryWrite, }, 0x04),
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryRead, }, 0x02),
new KeyValuePair<DataSectionFlags[], uint>(new [] { DataSectionFlags.MemoryWrite, }, 0x08),
new KeyValuePair<DataSectionFlags[], uint>(new DataSectionFlags[] { }, 0x01),
};
result |= ladder.Where(x => x.Key.All(y => characteristics.HasFlag(y))).First().Value;
return result;
}
可能更易读的版本:
private static uint GetSectionProtection(DataSectionFlags characteristics)
{
uint result = 0;
if (characteristics.HasFlag(DataSectionFlags.MemoryNotCached))
{
// PageNoCache
result |= 0x200;
}
var ladder = new []
{
new { Flags = new [] { DataSectionFlags.MemoryExecute, DataSectionFlags.MemoryRead, DataSectionFlags.MemoryWrite, }, Value = (uint)0x40 },
new { Flags = new [] { DataSectionFlags.MemoryExecute, DataSectionFlags.MemoryRead, }, Value = (uint)0x20 },
new { Flags = new [] { DataSectionFlags.MemoryExecute, DataSectionFlags.MemoryWrite, }, Value = (uint)0x80 },
new { Flags = new [] { DataSectionFlags.MemoryExecute, }, Value = (uint)0x10 },
new { Flags = new [] { DataSectionFlags.MemoryRead, DataSectionFlags.MemoryWrite, }, Value = (uint)0x04 },
new { Flags = new [] { DataSectionFlags.MemoryRead, }, Value = (uint)0x02 },
new { Flags = new [] { DataSectionFlags.MemoryWrite, }, Value = (uint)0x08 },
new { Flags = new DataSectionFlags[] { }, Value = (uint)0x01 },
};
result |= ladder.Where(x => x.Flags.All(y => characteristics.HasFlag(y))).First().Value;
return result;
}