I often do this when necessary to prevent a null pointer exception:
// Example #1
if (cats != null && cats.Count > 0)
{
// Do something
}
In #1, I've always just assumed that the cats != null needs to be first, because order of operations evaluate from left to right.
However, unlike example #1, now I want to do something if the object is null or if the Count is zero, therefore I'm using logical OR instead of AND:
// Example #2
if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
// Do something
}
Does the order of the logical comparisons matter? Or can I also reverse the order and get the same results, such as in Example #3?
// Example #3
if (table.Rows.Count <= 0 || table.Rows == null || table == null)
{
// Do something
}
(btw, I realize I can rewrite #2 like below, but I think it's messy, and I'm still curious about the OR operators)
// Example #4
if (!(table != null && table.Rows != null && table.Rows.Count > 0))
{
// Do something
}
In the example you provide:
if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
// Do something
}
...neither table.Rows, nor table.Rows.Count, will be dereferenced if tables is null.
That's because, with C# logical operators, order of operations matter. C# logical operators are short-circuiting - they evaluate from left to right, and if any result causes the rest of the expression to be moot, the rest of the expression will not be evaluated.
Consider this code:
bool A()
{
return false;
}
bool B()
{
return true;
}
//...
if (A() && B())
{
// do something
}
For an AND clause to be true, all elements must be true. However, A() returns false, and the runtime (or maybe the compiler here, in an optimization step, but let's not worry about that...) won't evaluate B() at all.
The same holds true for OR (||) expressions. If any element in the clause is true, evaluated left to right, the rest of the clause won't be executed.
Yes, the short-circuiting happens in both cases, the only difference being that && stops if the LHS is false (because the overall expression must then be false) while || stops if the LHS is true (because the overall expression must be true).
The first two examples in your question are correct, the third will throw an exception if table or table.Rows are null.
You should note that not all C# logical operators exhibit short-circuting behaviour (as was indicated above).
You are using the Conditional-AND operator (&&) and that does short-circuit. However the AND (&) operator is exactly the same as the Conditional-AND without the short-circuit.
The same is true for the OR and Conditional-OR operators.
For Example:
//This will throw if cats is null, whatever order.
if (cats != null & cats.Count > 0){ }
//This will not. Due to short-circuting.
if (cats != null && cats.Count > 0){ }
The first construction is not the same as the second one. The first one is to use when you want to not do anything when the reference is null or Count is zero. The second construction would DO something when it is null or the count is zero... To make the second one the same as the first you would need to write:
if (table == null || table.Rows == null || table.Rows.Count <= 0 || )
{}
else
{
// Do something
}
And order does matter, even in the second one as you wrote it, it would crash if table was null when it tried to evaluate table.Rows.
Order matters. Its all about short circuiting. For ands, the first false it hits it stops evaluating, for ORs it stops as soon as it hits a true.
It will short circuit after the first evaulation and that is why you dont get the null pointer exception.
When you think about it think insert null for each object.
if (null== null || null.Rows == null || null.null.Count <= 0)
{
// Do something
}
Then evaluate each boolean
if( true || null.Rows == null || null.null.Count <=0)
If you see true that means stop. If you hit a "null". statement you will crash.
Example to illustrate a crash
if (null.null.Count <= 0 || null.Rows == null || null== null)
{
// CRASH... Do something
}
Order does not matter.
Clarification:
The order you place the statements in the IF statement will not affect whether or not the IF statement is gone into...and thus the result.
As another poster pointed out, it will however affect which ones are evaluated, but this doesn't affect the bottom line AFAIK.
Edit #JonHanna
I guess I looked at this from the perspective that the OP stated he is checking for NPE's prior when required (see the first line of his post). So if his code doesn't produce runtime errors, then order means nothing. I can't imagine why anyone would code an IF statement with a thought process of "if this IF statement causes a NPE" then it won't get evaluated...
Related
With the introduction of Null-Conditional Operators in C#, for the following evaluation,
if (instance != null && instance.Val != 0)
If I rewrite it this way,
if (instance?.Val != 0)
it will be evaluated to true if instance is a null reference; It behaves like
if (instance == null || instance.Val != 0)
So what is the right way to rewrite the evaluation using this new syntax?
Edit:
instance is a field of a big object which is deserialized from JSON. There are quite a few pieces of code like this, first check if the field is in the JSON, if it is, check if the Val property does NOT equal to a constant, only both conditions are true, do some operation.
The code itself can be refactored to make the logical flow more "making sense" as indicated by Peter in his comment, though in this question I am interested in how to use null-conditional operators with !=.
With Null-Conditional operator returned value can always be null
if ((instance?.Val ?? 0) != 0)
If instance was null, then instance?.Val will also be null (probably int? in your case). So you should always check for nulls before comparing with anything:
if ((instance?.Val ?? 0) != 0)
This means:
If instance?.Val is null (because instance is null) then return 0. Otherwise return instance.Val. Next compare this value with 0 (is not equal to).
You could make use of null coallescing operator:
instance?.Val ?? 0
When instance is null or instance is not null but Val is, the above expression would evaluate to 0. Otherwise the value of Val would be returned.
if ((instance?.Val).GetValueOrDefault() != 0)
the ? conditional operator will automatically treat the .Val property as a Nullable.
This question already has answers here:
Deep null checking, is there a better way?
(16 answers)
Closed 5 years ago.
Can anyone tell me how do I optimize below code.
if (report != null &&
report.Breakdown != null &&
report.Breakdown.ContainsKey(reportName.ToString()) &&
report.Breakdown[reportName.ToString()].Result != null
)
As others have mentioned, you can use the ?. operator to combine some of your null checks. However, if you're after optimizing for performance, you should avoid the double dictionary lookup (ContainsKey and index access), going for a TryGetValue instead:
MyType match = null; // adjust type
if (report?.Breakdown?.TryGetValue(reportName.ToString(), out match) == true &&
match?.Result != null)
{
// ...
}
Ayman's answer is probably the best you can do for C# 6, for before that what you have there is pretty much the best you can do if all those objects are nullable.
The only way to optimize this further is to be checking if those objects are null before even calling the code, or better yet proofing your platform so this particular function shouldn't even be called in the first place if the values are null.
If you are just getting the value from from the dictionary however you can also simplify with the null coalescing operater '??'
Example:
MyDictionary['Key'] ?? "Default Value";
Thus if the Value at that entry is null you'll get the default instead.
So if this is just a fetch I'd just go
var foo =
report != null &&
report.Breakdown != null &&
report.Breakdown.ContainsKey(reportName.ToString()) ?
report.Breakdown[reportName.ToString()].Result ?? "Default" :
"Default";
But if you are actually doing things in the loop, then yeah you're pretty much at the best you can get there.
For C# 6 and newer, you can do it this way:
if (report?.Breakdown?.ContainsKey(reportName.ToString()) == true &&
report.Breakdown[reportName.ToString()].Result != null)
You can use null conditional operator but only on C# 6
if ( report?.Breakdown?.ContainsKey(reportName.ToString()) == true &&
report.Breakdown[reportName.ToString()].Result != null )
Can you try below? Also probably better to ship it to a method.
// unless report name is already a string
string reportNameString = reportName.ToString();
if ( report?.Breakdown?.ContainsKey(reportNameString) &&
report.Breakdown[reportNameString].Result != null )
{
// rest of the code
}
I want to say if this property is (Null OR Equals "" OR contains "ImageNotAvailable") Then go ahead and do something. But when I try to use the code below, I get an object reference error. I was hoping by putting (Publisher.ThumbnailURL == null) at the beginning of the test, the other tests would be ignored, but I get error above.
if ((Publisher.ThumbnailURL == null) | (Publisher.ThumbnailURL == "") | (Publisher.ThumbnailURL.Contains("ImageNotAvailable")))
I can simply split these up into "If Else's" but is there a way to specify that if the first test is null, don't try and figure out the rest of the If statement which will cause it to error
Use || instead of |:
if ((Publisher.ThumbnailURL == null) || (Publisher.ThumbnailURL == "") || (Publisher.ThumbnailURL.Contains("ImageNotAvailable")))
|| Operator
The conditional-OR operator (||) performs a logical-OR of its bool
operands, but only evaluates its second operand if necessary.
Note that you could also use string.IsNullOrEmpty as commented by Raphaël Althaus:
if (string.IsNullOrEmpty(Publisher.ThumbnailURL) || Publisher.ThumbnailURL.Contains("ImageNotAvailable"))
Yep, use || to evaluate the expression as early as possible, also, using String.IsNullOrEmpty would make the statement more brief:
if (String.IsNullOrEmpty(Publisher.ThumbnailURL) || (Publisher.ThumbnailURL.Contains("ImageNotAvailable")))
Is it possible to merge the following statement:
if (a != null)
{
if (a.Count > 5)
{
// Do some stuff
}
}
to just 1 If statement and make it not to check the second condition when the first one is not satisfied. (like AndAlso keyword in VB.NET). something like:
if (a != null /* if it is null, don't check the next statement */ &&& a.Count > 5)
{
// Do some stuff
}
Simply:
if ((a != null) && (a.Count > 5)) {
// ...
}
In C#, the && operator short-circuits, meaning it only evaluates the right-hand expression if the left-hand expression is true (like VB.NET's AndElse).
The And keyword you are used to in VB.NET does not short-circuit, and is equivalent to C#'s & (bitwise-and) operator.
(Similarly, || also short-circuits in C#, and VB.NET's Or is like C#'s |.)
if ((a != null) && (a.Count > 5)) // Parentheses are nice, but not necessary
{
// Excitement goes here
}
In C#, && is indeed a "short circuit" operator — if the expression to its left is false, the expression to its right will not be evaluated.
You need the && operator to short-circuit the if statement:
if (a != null && a.Count > 5)
{
// Execute code
}
So, if a is null then there is no need to evaluate the second condition for the if statement to return a value of false and therefore not execute the code in the block.
Is there any difference between below two statements
if (null != obj)
and
if (obj != null)
If both treated same which will be preferable?
The first is a Yoda condition. Use it you should not.
The difference here is the code generated. The two will not generate the exact same code, but in practice this will have no bearing on the results or performance of the two statements.
However, if you create your own types, and override the inequality operator, and do a poor job, then it will matter.
Consider this:
public class TestClass
{
...
public static bool operator !=(TestClass left, TestClass right)
{
return !left.Equals(right);
}
}
In this case, if the first argument to the operator is null, ie. if (null != obj), then it will crash with a NullReferenceException.
So to summarize:
The code generated is different
The performance and end results should be the same
Except when you have broken code in the type involved
Now, the reason I think you're asking is that you've seen code from C, which typically had code like this:
if (null == obj)
Note that I switched to equality check here. The reason is that a frequent bug in programs written with old C compilers (these days they tend to catch this problem) would be to switch it around and forget one of the equal characters, ie. this:
if (obj = null)
This assigns null to the variable instead of comparing it. The best way to combat this bug, back then, would be to switch it around, since you can't assign anything to null, it's not a variable. ie. this would fail to compile:
if (null = obj)
No, but the second way is more common and more readable (and more logical in my opinion)
No, there is not. It's exactly the same.
The style null == obj is sometimes just used to prevent the common typo obj = null to not accidently assign null to a variable, but with != there's absolutely no reason to do so.
In .NET it won't actually compile for the typo obj = null.
So the compiler prevents you from accidently doing it.
The Yoda condition comes originally from other languages, where this compiler feature is missing.
They are exactly the same.
Some people prefer to put the null as the first part of the expression to avoid errors like this
if (obj = null) // should be obj == null
But of course this doesn't apply to the != operator, so in your example it's just a difference of style.
First type of statement came from C/C++, where was possible to pass not boolean values to condition verification. E.g. anything not 0 was true, and zero was false:
if (5) { } // true
if (0) { } // false
Sometimes it created problems if you forgot to type one '=' char:
if (x = 5) { } // this was true always and changed x value
if (x == 5) { } // this was true, if x was equal to 5
So, Yoda syntax was used, to receive compiler error in case one '=' was missed:
if (5 = x) { } // this was generating compiler error for absent-minded programmers
if (5 == x) { } // this was true, if x was equal to 5
C# allow only boolean value in conditions, So
if (x = 5) { } // this won't compile
if (x == 5) { } // this is true, if x was equal to 5
What about boolean types?
if (y = true) { }
if (y == true) { }
Well, this is useless code, because you can just write if (y).
Conclusion: Yoda syntax is gone with C/C++ and you do not need to use it anymore.
The use of the first form
if (blah == obj)
stems from the days when compilers would not catch if (obj = blah) i.e. unintentional assignment, unless compile warning level was set to maximum