Related
Like in this example:
public MatchResult GetResult(int home, int away)
{
if ( home == away )
return MatchResult.Draw;
else if ( home > away )
return MatchResult.HomeWins;
else if ( home < away )
return MatchResult.AwayWins;
throw new Exception("Should be impossible");
}
I know I could fix this with an else for the last statement, but I often prefer to be explicit. Of course this is a simplified situation for example purposes.
Next to that: is the reason why the compiler throws not all code paths return a value, because the situation is too complicated for the compiler or because for other reasons (like we can in theory change the value of home midway by unmanaged code from a different thread or something?)
I know I could fix this with an else for the last statement, but I often prefer to be explicit.
You can remain explicit without telling the compiler. Since the only reason to be explicit is to help human readers, a comment in place of the actual if gives you the best of both worlds: programmers see the condition, while compilers don't bother you with unnecessary throws or returns.
if ( home == away )
return MatchResult.Draw;
else if ( home > away )
return MatchResult.HomeWins;
else // if ( home < away )
return MatchResult.AwayWins;
In situations where you genuinely need to throw an exception because some branch is impossible to reach the best course of action is to use assertions:
if (!CheckNonNegative(arg)) {
throw new ArgumentException(nameof(arg));
}
...
if (arg == 0) {
... // Do something
} else {
Debug.Assert(arg > 0, "Method has checked arg to be non-negative");
... // Do something else
}
I would argue that (if an exception is to be thrown - I'd rather change the code) this should throw a NotSupportedException. Generally, this is the exception to throw if a method is called but the current state of the object doesn't support the method call at that time.
It's only a short stretch to say that, if the laws of logic have broken down, you're in an unsupported state and cannot complete the method.
So, to start, I have seen posts like this: How to find which condition is true without using if statement
It's not quite what I need, although the idea is pertinent, in that I would like it to be more readable code.
I think Switch is the best bet, but let me explain.
I have this statement:
if (input == string.Empty || typeComboBox.Text == null)
{
MessageBox.Show("Nothing to encrypt!", "Nothing Selected!");
return null;
}
So the idea here is that I used to have this statement broken into two "IF" statements, which isn't a huge deal, but for readability sake, and my on going effort of reducing code, I wanted to combine the statements into one.
If input is empty, I want the first argument in MessageBox.Show to appear, but not the second.
If typeComboBox.Text is null, I want the second option to appear, but not the first.
If they are both true statements, I want both to appear.
Now, my goal was to have these both done without the use of more than one test or method. Basically, I mean this: if I can find which condition is true and have the resultant data output within the same statement, that would be ideal.
I see switches being an option, and I don't understand them very well yet, but I think that would require me to make a decision method based on the outcome of this test, and send that outcome to the switch; which wouldn't be ideal, as I could simply have two if statements and less code.
Is there any way to do this in one statement? It's not necessary for this specific program, but I want to know for the future.
Thanks!
I am assuming that you started with this code:
if (input == string.Empty)
{
MessageBox.Show("Nothing to encrypt!");
return null;
}
if (typeComboBox.Text == null)
{
MessageBox.Show("Nothing Selected!");
return null;
}
I don't consider there to be anything wrong with this code at all, and this is probably the most readable. It will perform exactly as many tests as necessary, and no more. Any alternative will result in more tests being performed, even though you may wind up with less code. For example:
if (input == string.Empty || typeComboBox.Text == null)
{
MessageBox.Show((input == string.Empty) ? "Nothing to encrypt!" : "Nothing Selected!");
return null;
}
Less lines of code, but in a failure scenario there will be two or three tests performed instead of one or two. It's also a bit less straightforward.
Terse code is nice, but make it too terse and it becomes harder to maintain. Readability lies somewhere between verbose and terse, and in this case the more verbose code is more readable, in my opinion.
Another option is to consider the fact that it would be appropriate to report multiple errors. For that, try code like this:
List<string> errors = new List<string>();
if (input == string.Empty)
{
errors.Add("Nothing to encrypt.");
}
if (typeComboBox.Text == null)
{
errors.Add("Nothing selected.");
}
if (errors.Count != 0)
{
MessageBox.Show(string.Join(" ", errors.ToArray()));
return null;
}
This is a bit more verbose than your original code, but it will allow all relevant errors to be reported instead of only the first one encountered.
#millimoose's comment is right on; two if statements would be the cleanest thing for your code. However, if you're wanting to expand your validations to a large number or establish a general pattern for validations of this sort, you could do something like set up a validation table:
public class ValidationRule
{
public ValidationRule(Func<bool> test, string errorMessage)
{
this.Test = test;
this.ErrorMessage = errorMessage;
}
public Func<bool> Test { get; private set; }
public string ErrorMessage { get; private set; }
}
var validationRules = new[] {
new ValidationRule(() => input != string.Empty, "Nothing to encrypt!"),
new ValidationRule(() => typeComboBox.Text != null, "Nothing Selected!")
};
With a table like this, you could then have code like this:
var errors = validationRules.Where(r => !r.Test()).Select(r => r.ErrorMessage);
if (errors.Any())
{
MessageBox.Show(string.Join(' ', errors));
return null;
}
If, however, you're only looking for something for your two conditions, then this is over-engineering.
I'd suggest a slightly different pattern that might be more readable:
StringBuilder message = new StringBuilder();
if (input == string.Empty) message.Append("Nothing to encrypt!\n");
if (typeComboBox.Text == null) message.Append("Nothing selected!\n");
// ... repeat as many times as desired ...
if (message.Length > 0) {
MessageBox.Show(message);
return null;
} else {
// proceed with your code here
}
This code has the advantage that it can show multiple messages, if more than one is valid. It can be frustrating for a user to see only one message at a time, if they have to go back, fix something, hit submit, and see a different error message.
There isn't a way in code to have three (seemingly) different actions decided by a single logical statement. If you try to break it down to the simplest logical (not in code, but just mental logic) flow you still end up with something like:
If A is true then do B
If C is true then do D
If both A and C is true do B and D
That can be simplified by noting (as you did) that each condition is actually separate from the other:
If A is true then B is always done
If C is true then D is always done
So, in your code, the simplest breakdown is
if (input == string.empty)
{
// Do some stuff
}
if (typeComboBox.Text == null)
{
// Do some other stuff
}
Now, rather than have a long complicated set of instructions on either method - you can simplify the look of your code by making this simply a decision section, that calls other methods to do the work:
if (input == string.empty)
{
this.PrimeInputs(); // or something
}
if (typeComboBox.Text == null)
{
this.InitTextBoxes(); // or something
}
The main thing is, this is different than a logical AND and logical OR since you want one action or the other - in some cases, and neither action if both cases are false, and both actions if both cases are true.
I wouldn't say this is better than a couple "if" statements, but it is only one.
var message =
((input==string.Empty ?
"Nothing to encrypt! " :
"") +
(typeComboBox.Text == null ?
"Nothing Selected!" :
"")).Trim();
if (message != "") {
MessageBox.Show(message);
return null;
}
Generally speaking, though, I like using conditional operators to construct logic trees that result in a single outcome, it's much more terse than a bunch of nested if/else clauses. As long as you indent properly I find such structures highly readable and expressive. Unfortunately in this case it's not ideal because you have outcomes that depend on combinations of your operands. Using this kind of logic to build a string probably isn't the best idea, though it is still probably the most terse option.
I have a class method that looks like this:
private List<string> DataStoreContents = new List<string>(new[] { "", "", "", "" });
public void InputDataStore(int DataStore, string Data)
{
DataStoreContents[DataStore - 1] = Data;
}
I want to make sure that DataStore is >=1 and <= 4
How can I write a unit test that ensures that?
Either
Assert.IsTrue(DataStore >= 1 && DataStore <= 4);
or, if you prefer the fluent interface
Assert.That(DataStore, Is.GreaterThanOrEqualTo(1).And.LessThanOrEqualTo(4));
[EDIT - in response to you clarification above]
It sounds like you want to have some sort of barrier checking to check that the supplied values are in range.
In this case, you have a few choices:
Philip Fourie has given an answer involving code contracts.
Another simple approach is to write the barrier check yourself:
public void InputDataStore(int DataStore, string Data)
{
if (DataStore < 1 || DataStore > 4)
{
throw new ArgumentOutOfRangeException("DataStore", "Must be in the range 1-4 inc.");
}
DataStoreContents[DataStore - 1] = Data;
}
If you don't want to throw an exception, but maybe want to log it and exit cleanly:
public void InputDataStore(int DataStore, string Data)
{
if (DataStore < 1 || DataStore > 4)
{
// log something here and then return
return;
}
DataStoreContents[DataStore - 1] = Data;
}
To link back to unit testing. A unit test, for example, could be a test you write to check that when InputDataStore is called with a value that is out of range, that it throws an expcetion. Another would be that when it is called with a value in range, it doesn't throw an exception, and it updates DataStoreContents correctly.
Assert.IsTrue(DataStore >= 1 && DataStore <= 4);
Perhaps this? (should all fail until you fix)
[Test]
[TestCase(5)]
[TestCase(0)]
[TestCase(int.MaxValue)]
[TestCase(int.MinValue)]
public void InvalidIndices(int index)
{
Assert.DoesNotThrow(() => yourObj.InputDataStore(index, "don't care"));
}
or (should all pass)
[Test]
[TestCase(5)]
[TestCase(0)]
[TestCase(int.MaxValue)]
[TestCase(int.MinValue)]
public void InvalidIndices(int index)
{
Assert.Throws<IndexOutOfRangeException>(() => yourObj.InputDataStore(index, "don't care"));
}
You can also use a code contract with a lot of other benefits such a static code checking.
This means that you will be warned during 'code time' about using the method incorrectly.
public void InputDataStore(int DataStore, string Data)
{
Contract.Requires(DataStore >= 1 && DataStore <= 4);
DataStoreContents[DataStore - 1] = Data;
}
A good read here: http://devjourney.com/blog/code-contracts-part-1-introduction/
I think you cannot really "test" here.
You can insert a check, which will be executed at runtime. Said check might help but it will not be that much more helpful than the ArrayOutOfBoundsException you'd get anyway...
Also, inserting a check is not the same thing as testing.
You should look at the Callers of the InputDataStore Function.
These you can test: Create some different situations, execute the callers and check whether they pass the right value to InputDataStore.
Consider the following function:
public enum Operator
{
EQUAL = 1,
GREATER_THAN = 2
}
public class checkString
{
public static bool isValid(string inputString, string checkString, Operator operation)
{
switch (operation)
{
case Operator.EQUAL:
if (inputString == checkString)
return true;
break;
case Operator.GREATER_THAN:
// Numeric check for greater than
try
{
double inputDouble, checkDouble;
inputDouble = Convert.ToDouble(inputString);
checkDouble = Convert.ToDouble(checkString);
if (inputDouble > checkDouble)
return true;
}
catch (Exception)
{ }
// Date check for greater than
try
{
DateTime inputDate, checkDate;
inputDate = DateTime.Parse(inputString);
checkDate = DateTime.Parse(inputString);
if (inputDate. > checkDate)
return true;
}
catch (Exception)
{ }
break;
}
return false;
}
}
Parameters
inputString: What we want to evaluate
checkString: The criteria (value) that the input must evaluate against
Operator: Enum for the operation we want to perform
Other things to know
Each line in a file is evaluated against this method to return if a condition has been met
The process of evaluating the records in the file checks line by line, in one instance that its equal to the condition. It may also check that the same line is also greater than the condition. Once the checks are done, it moves to the next record
There are no additional event listeners hooked up other than whatever defaults are in place, I am not pushing extra data to debug or trace logs
Problem
What people are going to evaluate is unknown to me at any point in this process but I need to be able to check that 'something' (regardless of what) is equal to, greater than or less than something else. Sure I check other things but I've simplified this function greatly.
That said, using EQUAL or NOT_EQUAL runs fast as can be, processing records in a very large file against said criteria pretty quick and efficiently. Once I added the GREATER_THAN logic, its slow... to the point where it takes minutes to process 20 meg files that used to take half a minute tops.
From what I can tell:
Exceptions are thrown all over the place. There is no guarantee that a field is going to be numeric or of date type. So I must attempt to cast to these data types to attempt to evaluate the condition
When exceptions are thrown, the console gets output where I have not instructed it to do so, its sort of automated
Yes I have a lack of experience in this area and am looking to learn more about exception handling and what really happens behind the scenes because when the other 80% of the records are not numeric, thats a lot of exceptions in a 20 meg, 80 thousand record file.
Is there a better way to handle the cast itself to increase efficiency? I've seen double.Parse / TryParse and can direct cast in front but am not sure which benefits the most.
Use double.TryParse and DateTime.TryParse instead of Convert.ToDouble and DateTime.Parse respectively.
Example:
double result;
if (double.TryParse(someString, out result))
{
Console.WriteLine(result);
}
else
{
// not a valid double
}
You can use TryParse() on those data types. Exceptions are messy and expensive. TryParse will return true/false if it worked or not while NOT throwing an exception. So you can just check the results of the call. Much more efficient than exceptions.
Convert.ToDouble() and Double.Parse() will throw exceptions.
try this code. It isn't the best, but it's better than what you have now considering you don't know what the type could be:
public static bool isValid(string inputString, string checkString, Operator operation)
{
double dblTmp1;
double dblTmp2;
if (Double.TryParse(inputString, out dblTmp1) && double.TryParse(checkString, out dblTmp2))
{
return Compare<Double>(dblTmp1, dblTmp1, operation);
}
DateTime dtTmp1;
DateTime dtTmp2;
if (DateTime.TryParse(inputString, out dtTmp1) && DateTime.TryParse(checkString, out dtTmp2))
{
return Compare<DateTime>(dtTmp1, dtTmp2, operation);
}
throw new InvalidOperationException("Unknown type");
}
public static bool Compare<T>(T obj1, T obj2, Operator operation) where T : IComparable
{
switch (operation)
{
case Operator.EQUAL:
{
return obj1.Equals(obj2);
}
case Operator.GREATER_THAN:
{
return obj1.CompareTo(obj2) > 0;
}
default:
{
throw new InvalidOperationException("Unknown operation");
}
}
}
Keep in mind that using exceptions slows down your program, because behind the scenes the runtime is creating an exception stack in order to be able to unwind this in case an exception is thrown. This stack is maintained regardless of whether your program throws or not, and that overhead is what slows you down the most.
The other answers are probably the best solution in this case, but in the general case you can improve your solution by catching the specific exception, which is probably NumberFormatException or ClassCastException. Catching Exception can cause all kinds of annoying, hard to trace problems (since you're not logging the exception).
Sometimes, I feel like it is easier to check if all of the conditions are true, but then only handle the "other" situation.
I guess I sometimes feel that it is easier to know that something is valid, and assume all other cases are not valid.
For example, let's say that we only really care about when there is something wrong:
object value = GetValueFromSomeAPIOrOtherMethod();
if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)))
{
// All the conditions passed, but we don't actually do anything
}
else
{
// Do my stuff here, like error handling
}
Or should I just change that to be:
object value = GetValueFromSomeAPIOrOtherMethod();
if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop)))
{
// Do my stuff here, like error handling
}
Or (which I find ugly):
object value = GetValueFromSomeAPIOrOtherMethod();
if(!((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop))))
{
// Do my stuff here, like error handling
}
Though rare for me, I sometimes feel that writing in this form leads to the clearest code in some cases. Go for the form that provides the most clarity. The compiler won't care, and should generate essentially (probably exactly) the same code.
It may be clearer, though, to define a boolean variable that is assigned the condition in the if () statement, then write your code as a negation of that variable:
bool myCondition = (....);
if (!myCondition)
{
...
}
Having an empty if block with statements in the else is ... just bad style. Sorry, this is one of my pet peeves. There is nothing functionally wrong with it, it just makes my eyes bleed.
Simply ! out the if statement and put your code there. IMHO it reduces the noise and makes the code more readable.
I should preface this by saying that it's my own personal preference, but I find myself usually pulling the validation logic out of the code and into its own validate function. At that point, your code becomes much "neater" by just saying:
if(!ValidateAPIValue(value))
That, in my mind, seems a lot more concise and understandable.
Just using the else part isn't acceptable. You needn't go to the trouble of applying De-Morgan's rule, just not the whole expresssion. That is, go from if (cond) to if (!(cond)).
I think it's completely unacceptable.
The only reason at all would be to avoid a single negation and pair of parentheses around the expression. I agree that the expressions in your example are horrible, but they are unacceptably convoluted to begin with! Divide the expression into parts of acceptable clarity, store those into booleans (or make methods out of them), and combine those to make your if-statement condition.
One similar design I do often use is exiting early. I don't write code like this:
if (validityCheck1)
{
if (validityCheck2)
{
// Do lots and lots of things
}
else
{
// Throw some exception, return something, or do some other simple cleanup/logic (version 2)
}
}
else
{
// Throw some exception, return something, or do some other simple cleanup/logic. (version 1)
}
Instead I write this:
if (!validityCheck1)
{
// Throw some exception, return false, or do some other simple logic. (version 1)
}
if (!validityCheck2)
{
// Throw some exception, return false, or do some other simple logic. (version 2)
}
// Do lots and lots of things
This has two advantages:
Only a few input cases are invalid, and they have simple handling. They should be handled immediately so we can throw them out of our mental model as soon as possible and fully concentrate on the important logic. Especially when there are multiple validity checks in nested if-statements.
The block of code that handles the valid cases will usually be the largest part of the method and contain nested blocks of its own. It's a lot less cluttered if this block of code is not itself nested (possibly multiple times) in an if-statement.
So the code is more readable and easier to reason about.
Extract your conditions, then call
if(!ConditionsMetFor(value))
{
//Do Something
}
Although this is not always practical, I usually prefer to change
if (complexcondition){} else {/*stuff*/}
to
if (complexcondition) continue;
/*stuff*/
(or break out with return, break, etc.). Of course if the condition is too complex, you can replace it with several conditions, all of which cause the code to break out of what it is doing. This mostly applies to validation and error-checking types of code, where you probably want to get out if something goes wrong.
If I see an "if", I expect it to do something.
if(!condition)
is far more readable.
if(condition) {
//do nothing
}
else {
//do stuff
}
essentially reads, "If my condition is met, do nothing, otherwise do something."
If we are to read your code as prose (which good, self-documenting code should be able to be read in that fashion) that's simply too wordy and introduces more concepts than necessary to accomplish your goal. Stick with the "!".
This is bad style, consider some very useful alternatives:
Use a guard clause style:
object value = GetValueFromSomeAPIOrOtherMethod();
if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)))
{
return;
}
// do stuff here
Extract the conditional into its own method, this keeps things logical and easy to read:
bool ValueHasProperty(object value)
{
return (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop));
}
void SomeMethod()
{
object value = GetValueFromSomeAPIOrOtherMethod();
if(!ValueHasProperty(value))
{
// do stuff here
}
}
Your question is similar to my answer(simplifying the conditions) on favorite programmer ignorance pet peeve's
For languages that don't support an until construct, chaining multiple NOTs makes our eyes bleed
Which one is easier to read?
This:
while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key)
Or this:
until (keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)
I am of the opinion that the latter is way easier to grok than the first one. The first one involves far too many NOTs and AND conditions makes the logic more sticky, it forces you to read the entire expression before you can be sure that your code is indeed correct, and it will be far more harder to read if your logic involves complex logic (entails chaining more ANDs, very sticky).
During college, De Morgan theorem is taught in our class. I really appreciate that logics can be simplified using his theorem. So for language construct that doesn't support until statement, use this:
while !(keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)
But since C don't support parenthesis-less while/if statement, we need to add parenthesis on our DeMorgan'd code:
while (!(keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key))
And that's what could have prompted Dan C's comment that the DeMorgan'd code hurts his eyes more on my answer on favorite programmer ignorance pet peeve's
But really, the DeMorgan'd code is way easier to read than having multiple NOTS and sticky ANDs
[EDIT]
Your code (the DeMorgan'd one):
object value = GetValueFromSomeAPIOrOtherMethod();
if ( value == null || string.IsNullOrEmpty(value.Prop)
|| !possibleValues.Contains(value.prop) )
{
// Do my stuff here, like error handling
}
..is perfectly fine. In fact, that's what most programmers(especially from languages that don't have try/catch/finally constructs from the get-go) do to make sure that conditions are met(e.g. no using of null pointers, has proper values, etc) before continuing with the operations.
Note: I took the liberty of removing superfluous parenthesis on your code, maybe you came from Delphi/Pascal language.
I do it when my brain can easily wrap itself around the logic of the success but it is cumbersome to understand the logic of the failure.
I usually just put a comment "// no op" so people know it isn't a mistake.
This is not a good practice. If you were using ruby you'd do:
unless condition
do something
end
If your language doesn't allow that, instead of doing
if(a){}else{something}
do
if(!a){something}
I find it to be unacceptable (even though I'm sure I've done it in the past) to have an empty block like that. It implies that something should be done.
I see the other questions state that it's more readable the second way. Personally, I say neither of your examples is particularly readable. The examples you provided are begging for an "IsValueValid(...)" method.
I occasionally find myself in a related but slightly different situation:
if ( TheMainThingIsNormal () )
; // nothing special to do
else if ( SomethingElseIsSpecial () ) // only possible/meaningful if ! TheMainThingIsNormal ()
DoSomethingSpecial ();
else if ( TheOtherThingIsSpecial () )
DoSomethingElseSpecial ();
else // ... you see where I'm going here
// and then finish up
The only way to take out the empty block is to create more nesting:
if ( ! TheMainThingIsNormal () )
{
if ( SomethingElseIsSpecial () )
DoSomethingSpecial ();
else if ( TheOtherThingIsSpecial () )
DoSomethingElseSpecial ();
else // ...
}
I'm not checking for exception or validation conditions -- I'm just taking care of special or one-off cases -- so I can't just bail out early.
My answer would usually be no....but i think good programming style is based on consistency.....
so if i have a lot of expressions that look like
if (condition)
{
// do something
}
else
{
// do something else
}
Then an occasional "empty" if block is fine e.g.
if (condition)
{ } // do nothing
else
{
// do something else
}
The reason for this is that if your eyes sees something several times, their less likely to notice a change e.g. a tiny "!". So even though its a bad thing to do in isolation, its far likely to make someone maintaining the code in future realize that this particular if..else... is different from the rest...
The other specific scenerio where it might be acceptable is for some kind of state machine logic e.g.
if (!step1done)
{} // do nothing, but we might decide to put something in here later
else if (!step2done)
{
// do stuff here
}
else if (!step3done)
{
// do stuff here
}
This is clearly highlighting the sequential flow of the states, the steps performed at each (even if its nothing). Id prefer it over something like...
if (step1done && !step2Done)
{
// do stuff here
}
if (step1done && step2done && !state3Done)
{
// do stuff here
}
I like the second version. It makes code more clean. Actually this is one of the things I would ask to correct during the code review.
I always try and refactor out big conditions like this into a property or method, for readability. So this:
object value = GetValueFromSomeAPIOrOtherMethod();
if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop)))
{
// Do my stuff here, like error handling
}
becomes something like this:
object value = GetValueFromSomeAPIOrOtherMethod();
if (IsValueUnacceptable(value))
{
// Do my stuff here, like error handling
}
...
/// <summary>
/// Determines if the value is acceptable.
/// </summary>
/// <param name="value">The value to criticize.</param>
private bool IsValueUnacceptable(object value)
{
return (value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop))
}
Now you can always reuse the method/property if needed, and you don't have to think too much in the consuming method.
Of course, IsValueUnacceptable would probably be a more specific name.
1st:
object value = GetValueFromSomeAPIOrOtherMethod();
var isValidValue = (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop));
if(!isValidValue)
{
// Do my stuff here, like error handling
}
2cnd:
object value = GetValueFromSomeAPIOrOtherMethod();
if(!isValidAPIValue(value))
{
// Do my stuff here, like error handling
}
Are all the expressions really the same? In languages that support short-circuiting, making the change between ands and ors can be fatal. Remember &&'s use as a guard to prevent the other conditions from even being checked.
Be careful when converting. There are more mistakes made than you would expect.
In these cases you may wish to abstract the validation logic into the class itself to help un-clutter your application code.
For example
class MyClass
{
public string Prop{ get; set; }
// ... snip ...
public bool IsValid
{
bool valid = false;
if((value != null) &&
(!string.IsNullOrEmpty(value.Prop)) &&
(possibleValues.Contains(value.prop)))
{
valid = true
}
return valid;
}
// ...snip...
}
Now your application code
MyClass = value = GetValueFromSomewhere();
if( value.IsValie == false )
{
// Handle bad case here...
}
I'm a fan of DeMorgan's Rule which takes your ex3 and produces your ex2. An empty if block is a mental block imo. You have to stop to read the nothing that exists - then you have to wonder why.
If you have to leave comments like // This left blank on purpose; then the code isn't very self-explanatory.
The style that follow to have one block empty of if-else is considered as a bad style..
for good programming practice if you dont have to write in if block you need to put (!) 'Not' in if block ..no need to write else
If(condition)
//blank
else
//code
can be replaced as
if(!condition)
//code
this is a saving of extra line of code also..
I wouldn't do this in C#. But I do it in Python, because Python has a keyword that means "don't do anything":
if primary_condition:
pass
elif secondary_condition1:
do_one_thing()
elif secondary_condition2:
do_another_thing()
You could say that { } is functionally equivalent to pass, which it is. But it's not (to humans) semantically equivalent. pass means "do nothing," while to me, { } typically means "there used to be code here and now there isn't."
But in general, if I get to the point where it's even an issue whether sticking a ! in front of a condition makes it harder to read, I've got a problem. If I find myself writing code like this:
while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key)
it's pretty clear to me that what I'm actually going to want over the long term is more like this:
var activeKeys = new[] { escape_key, alt_f4_key, ctrl_w_key };
while (!activeKeys.Contains(keypress))
because that makes explicit a concept ("these keys are active") that's only implicit in the preceding code, and makes the logic "this is what you happens when an inactive key is pressed" instead of "this is what happens when a key that's not one ESC, ALT+F4 or CTRL+W is pressed."