Как я мог упростить эту длинную цепочку условных утверждений? - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть следующее перечисление

[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;
}

Я пытаюсь упростить длинную цепочку условных операторов внутри этого метода, но у меня возникают проблемы при этом.

Какой самый простой способ написать условные операторы внутри метода, покавсе еще поддерживает их функциональность?

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Я предлагаю словарь поиска, например:

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).Если вы добавите одну и ту же комбинацию в словарь дважды, вы получите ошибку.

0 голосов
/ 21 ноября 2018

Это лучшее, что я мог придумать в короткие сроки:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...