How could I simplify this long chain of conditional statements?
I have the following enum
[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
}
I am casting a uint variable with this enum like so
var testVariable = (DataSectionFlags) 1610612768;
I have a method that processes the above variable like this
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;
}
I'm attempting to simplify the long chain of conditional statements inside this method but am having trouble doing so.
What would be the simplest way to write the conditional statements inside the method whilst still maintaining their functionality?
c# performance if-statement
add a comment |
I have the following enum
[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
}
I am casting a uint variable with this enum like so
var testVariable = (DataSectionFlags) 1610612768;
I have a method that processes the above variable like this
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;
}
I'm attempting to simplify the long chain of conditional statements inside this method but am having trouble doing so.
What would be the simplest way to write the conditional statements inside the method whilst still maintaining their functionality?
c# performance if-statement
3
This code is pretty easy to follow. Not sure it needs to change. Shorter does not necessarily mean simpler. In fact, terse code with lots going on can be more confusing for others (or your future self) to maintain.
– Daniel
Nov 21 '18 at 1:40
I see. I just thought it was bad convention to have so many nested statements
– user10454073
Nov 21 '18 at 1:45
i agree with @Daniel, there's no problem with your code. as long as it is easy to understand
– gadasadox
Nov 21 '18 at 2:08
2
One of the easiest ways you can make this code more readable is to ask yourself every time you write a comment "how could I have avoided writing this comment?" If you hadconst uint PageNoCache = 0x200;
in your class , then the first line of your method isif (characteristics.HasFlag(DataSectionFlags.MemoryNotCached)) result |= PageNoCache;
and now you don't need a comment.
– Eric Lippert
Nov 21 '18 at 3:07
add a comment |
I have the following enum
[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
}
I am casting a uint variable with this enum like so
var testVariable = (DataSectionFlags) 1610612768;
I have a method that processes the above variable like this
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;
}
I'm attempting to simplify the long chain of conditional statements inside this method but am having trouble doing so.
What would be the simplest way to write the conditional statements inside the method whilst still maintaining their functionality?
c# performance if-statement
I have the following enum
[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
}
I am casting a uint variable with this enum like so
var testVariable = (DataSectionFlags) 1610612768;
I have a method that processes the above variable like this
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;
}
I'm attempting to simplify the long chain of conditional statements inside this method but am having trouble doing so.
What would be the simplest way to write the conditional statements inside the method whilst still maintaining their functionality?
c# performance if-statement
c# performance if-statement
asked Nov 21 '18 at 1:36
user10454073
3
This code is pretty easy to follow. Not sure it needs to change. Shorter does not necessarily mean simpler. In fact, terse code with lots going on can be more confusing for others (or your future self) to maintain.
– Daniel
Nov 21 '18 at 1:40
I see. I just thought it was bad convention to have so many nested statements
– user10454073
Nov 21 '18 at 1:45
i agree with @Daniel, there's no problem with your code. as long as it is easy to understand
– gadasadox
Nov 21 '18 at 2:08
2
One of the easiest ways you can make this code more readable is to ask yourself every time you write a comment "how could I have avoided writing this comment?" If you hadconst uint PageNoCache = 0x200;
in your class , then the first line of your method isif (characteristics.HasFlag(DataSectionFlags.MemoryNotCached)) result |= PageNoCache;
and now you don't need a comment.
– Eric Lippert
Nov 21 '18 at 3:07
add a comment |
3
This code is pretty easy to follow. Not sure it needs to change. Shorter does not necessarily mean simpler. In fact, terse code with lots going on can be more confusing for others (or your future self) to maintain.
– Daniel
Nov 21 '18 at 1:40
I see. I just thought it was bad convention to have so many nested statements
– user10454073
Nov 21 '18 at 1:45
i agree with @Daniel, there's no problem with your code. as long as it is easy to understand
– gadasadox
Nov 21 '18 at 2:08
2
One of the easiest ways you can make this code more readable is to ask yourself every time you write a comment "how could I have avoided writing this comment?" If you hadconst uint PageNoCache = 0x200;
in your class , then the first line of your method isif (characteristics.HasFlag(DataSectionFlags.MemoryNotCached)) result |= PageNoCache;
and now you don't need a comment.
– Eric Lippert
Nov 21 '18 at 3:07
3
3
This code is pretty easy to follow. Not sure it needs to change. Shorter does not necessarily mean simpler. In fact, terse code with lots going on can be more confusing for others (or your future self) to maintain.
– Daniel
Nov 21 '18 at 1:40
This code is pretty easy to follow. Not sure it needs to change. Shorter does not necessarily mean simpler. In fact, terse code with lots going on can be more confusing for others (or your future self) to maintain.
– Daniel
Nov 21 '18 at 1:40
I see. I just thought it was bad convention to have so many nested statements
– user10454073
Nov 21 '18 at 1:45
I see. I just thought it was bad convention to have so many nested statements
– user10454073
Nov 21 '18 at 1:45
i agree with @Daniel, there's no problem with your code. as long as it is easy to understand
– gadasadox
Nov 21 '18 at 2:08
i agree with @Daniel, there's no problem with your code. as long as it is easy to understand
– gadasadox
Nov 21 '18 at 2:08
2
2
One of the easiest ways you can make this code more readable is to ask yourself every time you write a comment "how could I have avoided writing this comment?" If you had
const uint PageNoCache = 0x200;
in your class , then the first line of your method is if (characteristics.HasFlag(DataSectionFlags.MemoryNotCached)) result |= PageNoCache;
and now you don't need a comment.– Eric Lippert
Nov 21 '18 at 3:07
One of the easiest ways you can make this code more readable is to ask yourself every time you write a comment "how could I have avoided writing this comment?" If you had
const uint PageNoCache = 0x200;
in your class , then the first line of your method is if (characteristics.HasFlag(DataSectionFlags.MemoryNotCached)) result |= PageNoCache;
and now you don't need a comment.– Eric Lippert
Nov 21 '18 at 3:07
add a comment |
2 Answers
2
active
oldest
votes
I suggest a lookup dictionary like:
var sectionProtection = new Dictionary<DataSectionFlags, uint>
{
[DataSectionFlags.TypeReg ] = 1,
[DataSectionFlags.TypeDsect ] = 2,
...
[DataSectionFlags.MemoryExecute | DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite] = 0x40,
...
};
Note you'll need a separate entry for every combination of flags. Given such, you can then replace your function with the statement
var testVariable = sectionProtection[(DataSectionFlags) 1610612768];
or, if not every combination is defined:
if (sectionProtection.TryGetValue((DataSectionFlags) 1610612768, out testVariable ))
I consider this not only simpler to understand, faster to run, but also more correct. It is too easy to miss a combination, to have the same combination return different values, or to include the same combination twice when creating a list of if ... else if ... else if ...
statements. If you miss a combination in a lookup dictionary you get an exception (or TryGetValue
returns false
). If you add the same combination to a dictionary twice you get an error.
add a comment |
This is the best that I could come up with at short notice:
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;
}
A possibly more readable version:
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;
}
4
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
1
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. Theladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.
– Enigmativity
Nov 21 '18 at 2:38
1
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain whatuint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.
– radarbob
Nov 21 '18 at 3:40
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404118%2fhow-could-i-simplify-this-long-chain-of-conditional-statements%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I suggest a lookup dictionary like:
var sectionProtection = new Dictionary<DataSectionFlags, uint>
{
[DataSectionFlags.TypeReg ] = 1,
[DataSectionFlags.TypeDsect ] = 2,
...
[DataSectionFlags.MemoryExecute | DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite] = 0x40,
...
};
Note you'll need a separate entry for every combination of flags. Given such, you can then replace your function with the statement
var testVariable = sectionProtection[(DataSectionFlags) 1610612768];
or, if not every combination is defined:
if (sectionProtection.TryGetValue((DataSectionFlags) 1610612768, out testVariable ))
I consider this not only simpler to understand, faster to run, but also more correct. It is too easy to miss a combination, to have the same combination return different values, or to include the same combination twice when creating a list of if ... else if ... else if ...
statements. If you miss a combination in a lookup dictionary you get an exception (or TryGetValue
returns false
). If you add the same combination to a dictionary twice you get an error.
add a comment |
I suggest a lookup dictionary like:
var sectionProtection = new Dictionary<DataSectionFlags, uint>
{
[DataSectionFlags.TypeReg ] = 1,
[DataSectionFlags.TypeDsect ] = 2,
...
[DataSectionFlags.MemoryExecute | DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite] = 0x40,
...
};
Note you'll need a separate entry for every combination of flags. Given such, you can then replace your function with the statement
var testVariable = sectionProtection[(DataSectionFlags) 1610612768];
or, if not every combination is defined:
if (sectionProtection.TryGetValue((DataSectionFlags) 1610612768, out testVariable ))
I consider this not only simpler to understand, faster to run, but also more correct. It is too easy to miss a combination, to have the same combination return different values, or to include the same combination twice when creating a list of if ... else if ... else if ...
statements. If you miss a combination in a lookup dictionary you get an exception (or TryGetValue
returns false
). If you add the same combination to a dictionary twice you get an error.
add a comment |
I suggest a lookup dictionary like:
var sectionProtection = new Dictionary<DataSectionFlags, uint>
{
[DataSectionFlags.TypeReg ] = 1,
[DataSectionFlags.TypeDsect ] = 2,
...
[DataSectionFlags.MemoryExecute | DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite] = 0x40,
...
};
Note you'll need a separate entry for every combination of flags. Given such, you can then replace your function with the statement
var testVariable = sectionProtection[(DataSectionFlags) 1610612768];
or, if not every combination is defined:
if (sectionProtection.TryGetValue((DataSectionFlags) 1610612768, out testVariable ))
I consider this not only simpler to understand, faster to run, but also more correct. It is too easy to miss a combination, to have the same combination return different values, or to include the same combination twice when creating a list of if ... else if ... else if ...
statements. If you miss a combination in a lookup dictionary you get an exception (or TryGetValue
returns false
). If you add the same combination to a dictionary twice you get an error.
I suggest a lookup dictionary like:
var sectionProtection = new Dictionary<DataSectionFlags, uint>
{
[DataSectionFlags.TypeReg ] = 1,
[DataSectionFlags.TypeDsect ] = 2,
...
[DataSectionFlags.MemoryExecute | DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite] = 0x40,
...
};
Note you'll need a separate entry for every combination of flags. Given such, you can then replace your function with the statement
var testVariable = sectionProtection[(DataSectionFlags) 1610612768];
or, if not every combination is defined:
if (sectionProtection.TryGetValue((DataSectionFlags) 1610612768, out testVariable ))
I consider this not only simpler to understand, faster to run, but also more correct. It is too easy to miss a combination, to have the same combination return different values, or to include the same combination twice when creating a list of if ... else if ... else if ...
statements. If you miss a combination in a lookup dictionary you get an exception (or TryGetValue
returns false
). If you add the same combination to a dictionary twice you get an error.
edited Nov 26 '18 at 19:37
answered Nov 21 '18 at 1:57
Dour High ArchDour High Arch
18.1k166679
18.1k166679
add a comment |
add a comment |
This is the best that I could come up with at short notice:
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;
}
A possibly more readable version:
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;
}
4
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
1
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. Theladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.
– Enigmativity
Nov 21 '18 at 2:38
1
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain whatuint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.
– radarbob
Nov 21 '18 at 3:40
add a comment |
This is the best that I could come up with at short notice:
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;
}
A possibly more readable version:
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;
}
4
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
1
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. Theladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.
– Enigmativity
Nov 21 '18 at 2:38
1
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain whatuint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.
– radarbob
Nov 21 '18 at 3:40
add a comment |
This is the best that I could come up with at short notice:
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;
}
A possibly more readable version:
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;
}
This is the best that I could come up with at short notice:
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;
}
A possibly more readable version:
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;
}
edited Nov 21 '18 at 3:55
answered Nov 21 '18 at 1:54
EnigmativityEnigmativity
77.7k966135
77.7k966135
4
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
1
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. Theladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.
– Enigmativity
Nov 21 '18 at 2:38
1
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain whatuint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.
– radarbob
Nov 21 '18 at 3:40
add a comment |
4
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
1
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. Theladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.
– Enigmativity
Nov 21 '18 at 2:38
1
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain whatuint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.
– radarbob
Nov 21 '18 at 3:40
4
4
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
Clever, but I find the original significantly more clear and readable (and thus maintainable)...
– TypeIA
Nov 21 '18 at 2:02
1
1
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. The
ladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.– Enigmativity
Nov 21 '18 at 2:38
@TypeIA - Yes, I agree. What makes this interesting is that this is configurable. The
ladder
can be changed at run-time or read from a config file. But I do agree that it's not as easy to follow.– Enigmativity
Nov 21 '18 at 2:38
1
1
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain what
uint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.– radarbob
Nov 21 '18 at 3:40
This is more maintainable. The KVP instantiations is a data structure that clearly associates flags; no triple nested if's needed! Comparatively, data structure always results in simpler code: 9 "result =" blocks collapse to 1 line! Modifying that if-else/if nest requires more mental energy and is necessarily more error prone than non-branching code. A 1-line comment will explain what
uint
(the value in the KV pair) is; this is an understandability issue, not readability. This answer is pleasantly readable vis-a-vis a nested control structure.– radarbob
Nov 21 '18 at 3:40
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404118%2fhow-could-i-simplify-this-long-chain-of-conditional-statements%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
This code is pretty easy to follow. Not sure it needs to change. Shorter does not necessarily mean simpler. In fact, terse code with lots going on can be more confusing for others (or your future self) to maintain.
– Daniel
Nov 21 '18 at 1:40
I see. I just thought it was bad convention to have so many nested statements
– user10454073
Nov 21 '18 at 1:45
i agree with @Daniel, there's no problem with your code. as long as it is easy to understand
– gadasadox
Nov 21 '18 at 2:08
2
One of the easiest ways you can make this code more readable is to ask yourself every time you write a comment "how could I have avoided writing this comment?" If you had
const uint PageNoCache = 0x200;
in your class , then the first line of your method isif (characteristics.HasFlag(DataSectionFlags.MemoryNotCached)) result |= PageNoCache;
and now you don't need a comment.– Eric Lippert
Nov 21 '18 at 3:07