Currently facing a rather.. trivial issue.
I have two error-handling conditions:
1. Triggers true if two lists are inequal.
For example:
2. Triggers true if the cachedList.Length is > than the newList.Length.
For example:
First method to check string equality is this:
if (!checkEquality(cachedList, newList))
{
// do something
}
Where checkEquality() is:
public bool checkEquality(List<string> cachedList, List<string> newList)
{
if (cachedList.SequenceEqual(newList))
{
return true;
}
else {
return false;
}
}
The second method I use is:
if (cachedList.Count > newList.Count)
{
// Do something
}
With this said, and understandingly, when a scenario where condition no. 2 is hit, where the cached list is greater than the new list, both my conditions get hit. Both the "inequal" and "greater than" condition is hit, and it's causing undesired behavior in my code.
In order to not satisfy both these conditions when error-handling number 2 is hit, I need to think of an alternative to detect "inequality" in method number 1.
EDIT: I decided to put in a condition to check if the counts of newList and cachedList are equal, and only check for their equality given their count is equal. Is this the right way to approach this?
public bool checkEquality(List<string> oldFirstList, List<string> newFirstList)
{
if (oldFirstList.Count == newFirstList.Count)
{
if (oldFirstList.SequenceEqual(newFirstList))
{
return true;
}
else
{
return false;
}
}
return true;
}
The second problem it´s right the cachedList.Count > newList.Count, and that´s the reason why the if is true.
if (cachedList.Count > newList.Count)
{
// Do something
}
This will "do something" because it´s true the condition
And your first problem, try something like this:
Instead of this:
if (!checkEquality(cachedList, newList))
{
// do something
}
Try this directly:
if (cachedList.SequenceEqual(newList))
{
return true;
}
else
{
return false;
}
This will return false;
According to the documentation for SequenceEqual, the length check is already being done there. Unless you have no other criteria other than length and equality, there is no need to wrap SequenceEqual into your own method. You can even define a type of IEqualityComparer<T> if you want to compare more than references.
Related
I have a method that checks multiple conditions to execute further, only to proceed to next if the current condition evaluates to false, otherwise the method will exit without evaluating further conditions. And the number of conditions vary in different implementations (subclasses).
I'm limited by my creativity to make it look any better than using the dreaded goto statement. Is there any better way to do the following:
public bool DoSomething()
{
bool result = true;
if (exclusion1)
{
result = false; goto Exit_Now;
}
if (exclusion2)
{
result = false; goto Exit_Now;
}
if (exclusion3)
{
result = false; goto Exit_Now;
}
if (exclusion4)
{
result = false; goto Exit_Now;
}
if (exclusion5)
{
result = false; goto Exit_Now;
}
if (result)
{
//do something
}
Exit_Now:
return result;
}
EDIT: In response to the answers, I understand using "else if" and conditional OR '||' operator are the obvious choices:
Subquery: which is more performant? I ask because this happens inside a loop and each evaluation takes about 30-40 ms. What is supposed to be finished in under a minute is taking up to two minutes without the goto statements in the code given above. Hence, the query. Thanks for all the help.
If you can fit your exclusion tests into the if statement, just use else if statements;
if (exclusion1)
{
result = false;
}
else if (exclusion2)
// etc ...
else if (result)
{
//do something
}
But I find it's much simpler, and easier to read, to just return early;
if (exclusion1)
return false;
One way to simplify this is to treat the exclusions as a guard clause:
public bool DoSomething()
{
if (exclusion1 ||
exclusion2 ||
exclusion3 ||
exclusion4 ||
exclusion5)
{
return false;
}
//do something
return true;
}
This also has the benefit of removing the nesting of the //do something towards the end.
you can always do this:
result = !(exclusion || exclustion2 ...|| exclusionN);
Switch case statements are good to replace nested if statements if we have the same condition but different criteria. But what is a good approach if those nested if statements all have different and unique conditions? Do I have any alternate options to replace a dozen if else statements nested inside each other?
Sample Code:
Note: I know this is extremely unreadable - which is the whole point.
Note: All conditions are unique.
...
if (condition) {
// do A
} else {
if (condition) {
// do B
if (condition) {
if (condition) {
if (condition) {
// do C
if (condition) {
// do D
if (condition) {
// do E
} else {
if (condition) {
// do F
}
}
}
}
if (condition) {
// do G
if (condition) {
// do H
if (condition) {
// do I
} else {
// do J
}
}
}
}
}
}
The best approach in this case is to chop up the thing into appropriately named separate methods.
I had to check this was Stackoverflow not DailyWTF when I saw the code!!
The solution is to change the architecture and use interfaces and polymorphism to get around all the conditions. However that maybe a huge job and out of the scope of an acceptable answer, so I will recommend another way you can kinda use Switch statements with unique conditions:
[Flags]
public enum FilterFlagEnum
{
None = 0,
Condition1 = 1,
Condition2 = 2,
Condition3 = 4,
Condition4 = 8,
Condition5 = 16,
Condition6 = 32,
Condition7 = 64
};
public void foo(FilterFlagEnum filterFlags = 0)
{
if ((filterFlags & FilterFlagEnum.Condition1) == FilterFlagEnum.Condition1)
{
//do this
}
if ((filterFlags & FilterFlagEnum.Condition2) == FilterFlagEnum.Condition2)
{
//do this
}
}
foo(FilterFlagEnum.Condition1 | FilterFlagEnum.Condition2);
#Tar suggested one way of looking at it. Another might be.
Invert it.
if (myObject.HasThing1)
{
if(myObject.HasThing2)
{
DoThing1();
}
else
{
DoThing2();
}
}
else
{
DoThing3();
}
could be
DoThing1(myObject.HasThing1);
DoThing2(myObject.HasThing2);
DoThing3(myObject.HasThing3);
So each Do method makes the minimum number of tests, if any fail the it does nothing.
You can make it a bit cleverer if you want to break out of the sequence in few ways.
No idea whether it would work for you, but delegating the testing of the conditions is often enough of a new way of looking at things, that some simplifying factor might just appear as if by magic.
In my point of view there exists two main methods to eliminate nested conditions. The first one is used in more special cases when we have only one condition in each nested conditions like here:
function A(){
if (condition1){
if (condition2){
if (condition3){
// do something
}
}
}
}
we can just go out from the opposite condition with return:
function A(){
if (condition1 == false) return;
if (condition2 == false) return;
if (condition3 == false) return;
// do something
}
The second one is using a condition decomposition and can be treated as more universal than the first one. In the case when we have a condition structure like this, for example:
if (condition1)
{
// do this 1
}
else
{
if (condition2)
{
// do this 2
}
}
We can implement a variables for each particular condition like here:
bool Cond1 = condition1;
bool Cond2 = !condition1 && condition2;
if (Cond1) { //do this 1 }
if (Cond2) { //do this 2 }
If that really is the business logic then the syntax is OK. But I have never seen business logic that complex. Draw up a flow chart and see if that cannot be simplified.
if (condition)
{
// do this
}
else
{
if (condition)
{
// do this
}
}
can be replaced with
if (condition)
{
// do this
}
else if (condition)
{
// do this
}
But again step back and review the design. Need more than just an else if clean up.
I feel your pain.
My situation required writing many (>2000) functional tests that have been customer specified for a large, expensive piece of equipment. While most (>95%) of these tests are simple and have a straight forward pass/fail check dozens fall into the "multiple nested if this do that else do something different" at depths similar or worse than yours.
The solution I came up with was to host Windows Workflow within my test application.
All complex tests became Workflows that I run with the results reported back to my test app.
The customer was happy because they had the ability to:
Verify the test logic (hard for non programmers looking at deeply nested if/else C# - easy looking at a graphical flowchart)
Edit tests graphically
Add new tests
Hosting Windows Workflow (in .NET 4/4.5) is very easy - although it may take you a while to get your head around "communications" between the Workflows and your code - mostly because there are multiple ways to do it.
Good Luck
(couldn't think of a better title, feel free to edit it to a title that describes the question better)
I have the following method:
bool CalculateNewState(int adjacent, bool currentState)
{
if (currentState == true)
{
foreach (int n in liveRule)
{
if (adjacent == n)
{
return true;
}
}
return false;
}
else
{
foreach (int n in becomeAliveRule)
{
if (adjacent == n)
{
return true;
}
}
return false;
}
}
This is for a game of life clone. What I want to implement is that a user can make his own rules.
The bool currentState tells the method whether the cell is alive or not. the int adjacent tells the method how many alive neighbors the cell has.
What I want to achieve with this is that when the user says:
2,3 and 5 neighbors keep the cell alive. That it will iterate through an array (liveRule) that holds 2,3 and 5. when any match occurs it should return true, else false.
What happens here is that, after returning a true, it keeps iterating and will eventually return whether the last element in liveRule matched.
What do I need to do, to stop iterating after a match has occurred?
It is of course possible I'm taking the wrong approach to this problem. I started from the suggestions here.
(tried to describe it to the best of my abilities, but it still seems quite unclear)
This is C# in Unity3D.
The code you've implemented says "if adjacent is unequal to any of 2, 3 or 5, then return". Obviously adjacent cannot be equal to all of them!
Start over. Rename your methods so that they are more clear. Booleans should answer a true/false question, so choose names that ask a question:
bool IsCellAlive(int adjacentCount, bool isAlive)
{
if (isAlive)
return liveRule.Contains(adjacentCount);
else
return deadRule.Contains(adjacentCount);
}
"Contains" is slower than a foreach loop, so this might cause a performance problem. Don't worry about it for now; you haven't even got the code correct yet. Write the code so that it is obviously correct, and then use a profiler to find the slow spot if it is not fast enough.
Remember: make it correct, then make it clear, then make it fast.
Your return statements will exit the CalculateNewState method immediately. If you find that the iteration is continuing, either you are not hitting the return statements (adjacent == n is never true), or possibly CalculateNewState is being called repeatedly from elsewhere in your code.
You can probably rewrite it much more simply to something like:
if (currentState)
return liveRule.Contains(adjacent);
return becomeAliveRule.Contains(adjacent);
Well you can always use a "break" statement to terminate the loop. Do something like:
bool CalculateNewState(int adjacent, bool currentState)
{
if(currentState)
{
return IsStateMatch(adjacent, liveRule);
}
else
{
return IsStateMatch(adjacent, becomeAliveRule);
}
}
bool IsStateMatch(int adjacent, int[] rules)
{
bool finalState = false;
if(rules != null)
{
for(int i = 0; i < rules.length; i++)
{
if(adjacent == rules[i])
{
finalState = true;
break;
}
}
}
return finalState;
}
I broke down the methods a little more, just for readability, but I think this is the basic idea. Now, I do agree with the other posters about what could be happening. If your loop is continuing after a break / return statement, then you most likely have buggy code elsewhere incorrectly calling the method.
It looks like your equality test is the culprit... shouldn't you be testing adjacent == n instead of adjacent != n? That way it will return true for the matches and only return false if no match.
The iterator will NOT continue after a return exits the loop.
Can you use a for loop instead of foreach with an additional variable?
bool CalculateNewState(int adjacent, bool currentState)
{
if (currentState == true)
{
bool match = false;
for(int n = 0; n < liveRule.length && !match; n++)
{
if (adjacent != n)
{
match = true;
}
}
return match;
}
else
{
bool match = false;
for(int n = 0; n < becomeAliveRule.length && !match; n++)
{
if (adjacent != n)
{
match = true;
}
}
return match;
}
}
Which is better of the following?
this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
or
this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
It needs be to true ONLY when the session is true. If the session is set to false will this evaluate to true in #2 as it exists? Or is it evaluating its value?
The second one:
this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
(bool)HttpContext.Current.Session["li"] is already a boolean (so will be either true or false), so no need for the extra comparison and return value of the boolean expression.
Either way, you need to check that the li session variable exists before trying to cast it, or your code will throw (I think a NullReferenceException).
The latter is clearer, IMO. They're functionally equivalent though - in both cases, it will fetch the value of "li" from the session and attempt to cast it to bool, throwing an exception if the value isn't present.
Create a property for the desired value:
public bool IsLoggedIn {
get { return (bool)HttpContext.Current.Session["li"]; }
}
You could even go one extra level, if the session is used a lot in the class:
public bool IsLoggedIn {
get { return (bool)Session["li"]; }
}
private HttpSessionState Session {
get { return HttpContext.Current.Session; }
}
Also, if you ever want to look at the session by itself, use a better key, like "IsLoggedIn", instead of "li".
It might be good to create a special class for these application-wide values:
public static class MyAppSession {
const string IsLoggedInKey = "IsLoggedIn";
public static bool IsLoggedIn {
get {
return Session[IsLoggedInKey] != null && (bool)Session[IsLoggedInKey];
}
internal set { Session[IsLoggedInKey] = value; }
}
// ...
private static HttpSessionState Session {
get { return HttpContext.Current.Session; }
}
}
The first and the second approach is equivalent, but the first one is to verbose for my taste. I like the second one much better.
Just as I like this
bool accepted = true;
if( accepted)
{
..
}
Better than
bool accepted = true;
if( accepted == true)
{
..
}
I feel it clearer that way if the variables are properly named.
Just put the expected value in the place of the expression, and it will become pretty clear:
First example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
After: this.isLoggedIn = true == true;
Second example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
After: this.isLoggedIn = true;
Now, try the same for the false case:
First example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
After: this.isLoggedIn = false == true;
Second example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
After: this.isLoggedIn = false;
As you can see, there will be no difference in the result between the two approaches. It all comes down to questions about coding style and readability, where I would guess that you would find a bias towards the shorter version.
You never need to write code that says:
bool x = (y == true);
Instead just use
bool x = y;
In your specific case you should use:
this.isLoggedIn = HttpContext.Current.Session["li"] != null
&& (bool)HttpContext.Current.Session["li"];
This way you will not get an exception if Session["li"] has not been assigned yet. However you will get an exception if Session["li"] is not castable to bool.
I would use the second option with a variant:
this.isLoggedIn = (bool) (HttpContext.Current.Session["li"] ?? "false");
The ?? is null-coalescing operator - it gives a value of "false" to the expression on its lefthand side, in case it happens to be null.
Both pieces of code are equal, so the better is the second (it's shorter).
I came across the following expression in someone else's code. I think it's terrible code for a number of reasons (not least because it fails to take into account bool.TrueString and bool.FalseString), but am curious as to how the compiler will evaluate it.
private bool GetBoolValue(string value)
{
return value != null ? value.ToUpper() == "ON" ? true : false : false;
}
Edit
Incidentally, aren't the expressions evaluated from the inside-outwards? In this case, what's the point of checking for value != null after the call to value.ToUpper() which will throw a null reference exception?
I think the following is a correct (deliberately) verbose version (I'd never leave it like this :D ):
if (value != null)
{
if (value.ToUpper() == "ON")
{
return true;
}
else // this else is actually pointless
{
return false;
}
}
else
{
return false;
}
Which can be shortened to:
return value != null && value.ToUpper == "ON";
Is this a correct re-writing of the expression?
It looks like the method is indended to handle a value that comes from a checkbox HTML element. If no value is specified for the checkbox, it uses the value "on" by default. If the checkbox is not checked there is no value at all from it in the form data, so reading the key from Request.Form gives a null reference.
In this context the method is correct, althought it's quite horrible due to the use of the if-condition-then-true-else-false anti-pattern. Also it should have been given a name that is more fitting for it's specific use, like GetCheckboxValue.
Your rewrite of the method is correct and sound. As the value is not culture dependant, converting the value to uppercase should not use the current culture. So a rewrite that is even slightly better than the one that you proposed would be:
return value != null && value.ToUpperInvariant == "ON";
(The culture independent methods are also a bit faster than the ones using a specific culture, so there is no reason not to use them.)
Incidentally, aren't the expressions
evaluated from the inside-outwards?
If it was method calls so that all expressions were actually evaluated, they would, as the inner call has to be made to evaluate the parameters for the outer call.
However, the second and third operands of the conditional expression is only evaluated if they are used, so the expressions are evaluated from the outside and inwards. The outermost condition is evaluated first to decide which of the operands it will evaluate.
You are correct, both in your rewriting and in your assertion that this attempt at conciseness is bad because it leads to confusion.
well the first one is a double-nested ternary operator
return (value != null) ? [[[value.ToUpper() == "ON" ? true : false]]] : false;
The bit in [[[ ]]] is the first result of the ternary expression which gets evaluated
when the first condition is true so you're reading/assertion of it is correct
but its ugly as hell and very unreadable/unmaintainable in its current state.
I'd definitely change it to your last suggestion
SideNote:
People who do
if(X == true)
return true;
else
return false;
instead of
return X;
should be taken out and shot ;-)
Are you looking for speed or readability and organization? Speed of execution, your shortened example is probably the best way to go.
For a few extra milliseconds, you could re-write this utility method as an extension method like so:
public static bool ToBoolean(this string value)
{
// Exit now if no value is set
if (string.IsNullOrEmpty(value)) return false;
switch (value.ToUpperInvariant())
{
case "ON":
case "TRUE":
return true;
}
return false;
}
... and then you would use it as follows:
public static void TestMethod()
{
bool s = "Test".ToBoolean();
}
EDIT:
Actually, I'm wrong... a quick performance test shows that the extension method is FASTER than the inline method. The source of my test is below, as well as the output on my PC.
[Test]
public void Perf()
{
var testValues = new string[] {"true", "On", "test", "FaLsE", "Bogus", ""};
var rdm = new Random();
int RunCount = 100000;
bool b;
string s;
Stopwatch sw = Stopwatch.StartNew();
for (var i=0; i<RunCount; i++)
{
s = testValues[rdm.Next(0, testValues.Length - 1)];
b = s.ToBoolean();
}
Console.Out.WriteLine("Method 1: {0}ms", sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (var i = 0; i < RunCount; i++)
{
s = testValues[rdm.Next(0, testValues.Length - 1)];
b = s != null ? s.ToUpperInvariant() == "ON" ? true : s.ToUpperInvariant() == "TRUE" ? true : false : false;
}
Console.Out.WriteLine("Method 2: {0}ms", sw.ElapsedMilliseconds);
}
Output:
Method 1: 21ms
Method 2: 30ms
I read the original expression the same way you do. So I think your shortened expression is correct. If value is null it will never get to the second conditional, so it looks safe to me.
I also hate the constructs like:
if (value.ToUpper() == "ON")
{
return true;
}
else // this else is actually pointless
{
return false;
}
as you noticed it is a long and convoluted (not to say stupid) way of writing:
return value.ToUpper() == "ON";
Your proposition is nice, short and correct.
Another alternative:
return string.Equals( value, "ON", StringComparison.OrdinalIgnoreCase );