Boolean Or containing Ternary conditional operation doesn't get short-circuited - c#

In general, the short circuit or operator || ignores the right side of the or if the left side evaluates to true. Apparently, we've found an exception to this.
Check out the following:
if (foo == null || bar != true ? foo.Count == 0 : true)
{
}
This code throws a null reference exception on the command foo.Count because foo is null. And naturally, the boolean logic allows for this. But, if foo is null you would expect that the or would short circuit and not even evaluate the right side of the expression, but it still does, and it throws an exception.
Is this a bug in my code or in the C# compiler? Is there a part of the C# specification that handles this case?

That's because your statement isn't being evaluated as you expect.
You need some extra parenthesis:
if(foo == null || (bar != true ? foo.Count == 0 : true))
The way it's written now is equivalent to (due to operator precedence):
if((foo == null || bar != true) ? foo.Count == 0 : true)

No, it works correctly, refer to operator precedence. || will be evaluated before ?:
So it firstly evaluates foo == null || bar != true and then ? foo.Count == 0 : true, so it's more like:
if ((foo == null || bar != true) ? foo.Count == 0 : true)
{
}
If you want to use short-circut here then it should be:
if (foo == null || (bar != true ? foo.Count == 0 : true))
{
}

Imagine parentheses around the condition you're checking:
if ((foo == null || bar != true) ? foo.Count == 0 : true)
{
}
Thus, if foo is null, you're attempting to read foo.Count, which will naturally result in a NullReferenceException.

According to Operator precedence and associativity conditional operator ?: has lowest priority. Thus it will be executed last. Like this:
(foo == null || bar != true) ? foo.Count == 0 : true

Related

Null value is still evaluated after testing it with condition

I have the following LINQ query:
houses.Where(x =>
x.A && user.B
||
(x.Address == null || user.Address == null ? false : x.Address.CountryCode == user.Address.CountryCode
))
I get an error when user.Address is null in:
user.Address.CountryCode
To avoid that I tried to use:
x.Address == null || user.Address == null
But it seems user.Address.CountryCode is still evaluated.
How can I avoid that?
It's definitely EF Core 3.0 query translator defect.
For now (and in general) you can avoid it by not using conditional operator ?: for criteria expressions which need to be converted to SQL query parameters (like your user.Address.CountryCode), but the equivalent logical binary expressions.
e.g. instead of
(x.Address == null || user.Address == null ? false : x.Address.CountryCode == user.Address.CountryCode)
use the equivalent
(x.Address != null && user.Address != null && x.Address.CountryCode == user.Address.CountryCode)
Personally I find this logic confusing. You might try:
( (x?.Address?.CountryCode != null && user?.Address?.CountryCode != null) ? x.Address.CountryCode == user.Address.CountryCode : false
If that doesn't work then there is something very odd going on with the Address or CountryCode properties! Probably and entity framework issue.

Inline If statement - short-circuiting

As I understand and read you can use short circuiting in if statement (&& or ||) in order for second condition not to fire. and if you want both condition to fire you would use single operands (& or |).
So say if I have inline if statement as below :
var test = (MyObject != null || string.IsNullOrEmpty(MyObject.Property)) ? string.Empty : MyObject.Property;
This will throw object reference error if MyObject is null, which in my opinion should not as I am using short circuiting. Can someone please explain this.
You're using the wrong condition. This part:
MyObject != null || string.IsNullOrEmpty(MyObject.Property)
should be:
MyObject == null || string.IsNullOrEmpty(MyObject.Property)
The RHS of an || only executes if the left hand is false. You want it to only execute if MyObject is not null.
EDIT: If you really want the MyObject != null part, you could change the whole thing to:
var test = MyObject != null && !string.IsNullOrEmpty(MyObject.Property)
? MyObject.Property : "";
Note the reversal of the 2nd and 3rd operands of the conditional operator too though.
You should have an == not an !=
var test = (MyObject == null || string.IsNullOrEmpty(MyObject.Property) ? string.Empty : MyObject.Property
Try this:
var test = (MyObject == null || string.IsNullOrEmpty(MyObject.Property)
? string.Empty : MyObject.Property
MyObject != null || string.IsNullOrEmpty(MyObject.Property)
Here you say.
If my object is not null.
or
string.IsNullOrEmpty(MyObject.Property)
Which means that if MyObject is null he will try to execute the second part.
MyObject == null || string.IsNullOrEmpty(MyObject.Property)
This won't throw null exception
That happens because MyObject is null and therefore the first condition is false so the second part must be evaluated to know the whole of the condition. Change the line to this:
MyObject != null && string.IsNullOrEmpty(MyObject.Property)
You should prefer readability instead of line-count, e.g.:
string prop = string.Empty;
if(MyObject != null && MyObject.Property != null)
prop = MyObject.Property;
(the reason for your exception was already explained in other answers)

Using ternary operator to check if null - null reference is not the same as null

I am attempting to use the ternary operator to check if a value is null and return one expression or the other. What I'm experiencing when incorporating this into a LINQ expression is that the Transact-SQL translation of the LINQ expression attempts to do a "column = null" rather than a "column IS NULL". I have reason to believe that this is because I'm doing the following:
mappedColumnName == (myVar == null ? null : myOtherVar)
Since it translates the following to columnName IS NULL in Transact-SQL:
mappedColumnName == null
Does anyone have any experience with this? I'd very much like to get this to work.
The entire LINQ expression:
(from MenuItem in menuContext.Menus
where MenuItem.IsSysAdmin == (ClientID == 1 ? true : false)
&& MenuItem.IsActive == true
&& MenuItem.ParentMenuCode == (ActiveSubMenu==null?null:ActiveMenu)
&& MenuItem.ClientID == (UseClientMenu ? ClientID : 0)
&& MenuItem.EmployeeID == (UseEmployeeMenu ? EmployeeID : 0)
orderby MenuItem.SortOrder, MenuItem.MenuName
select MenuItem);
Why don't you use
mappedColumnName == (myVar == null ? DBNull.Value: myOtherVar)
instead?
I've never actually attempted to use ternary operators in linq although you could write it as:
(
(myVar == null && mappedColumnName == null ) ||
(myVar != null && mappedColumnNmae == myOtherVar)
)
try this
(from MenuItem in menuContext.Menus
where MenuItem.IsSysAdmin == ((ClientID == 1 )? true : false)
&& MenuItem.IsActive == true
&& MenuItem.ParentMenuCode == ( (ActiveSubMenu==null) ?null:ActiveMenu)
&& MenuItem.ClientID == (UseClientMenu ? ClientID : 0)
&& MenuItem.EmployeeID == (UseEmployeeMenu ? EmployeeID : 0)
orderby MenuItem.SortOrder, MenuItem.MenuName
select MenuItem);

Nully the null error

Is there a way to tell the program that i don't care if a class reference is null.
For example:
if (playermove[i].name == "punch" || ispunchactivated == true)
{
Do the punch;
}
Why is he searching for the playermove (that can be null) and give me a null exeption error? i really don't care if the ispunchactivated is true.
Thanks.
If you put your two conditions the other way around:
ispunchactivated /*== true*/ || playermove[i].name == "punch"
// this isn't necessary
then, if the first one is true, the second one won't be checked.
However, unless you know playermove[i] won't be null if ispunchactivated is false, you should really be making the null check too, otherwise you'll still get exceptions:
ispunchactivated ||
(playermove[i] != null && playermove[i].name == "punch")
You just check it for null first.
There are not shortcuts here.
if (playermove == null || playermove[i].name == "punch" || ispunchactivated == true)
{
Do the punch;
}
Try this,
if ((ispunchactivated == true) || (playermove[i] != null && playermove[i].name == "punch" ))
{
Do the punch;
}
You can modify the if condition as follows:
if (ispunchactivated == true || (playermove!=null && playermove[i].name == "punch" ))
Just interchange the conditions and shortcircuitting will do that for you:
if (ispunchactivated == true || playermove[i].name == "punch")
{
Do the punch;
}
playermove[i] is only evaluated if ispunchactivated is false. That being said, you can still run into a null pointer exception if ispunchactivated is false and playermove[i] is null.
Change your condition as follows:
if(playermove !=null && playermove[i] != null)
{
if (playermove[i].name == "punch" || ispunchactivated == true)
{
Do the punch;
}
}

more short code about if statement

i wanted to try the following code:
//all arrays are List<T> type.
if (m.terms[0] != null && m.terms[0].labels != null && m.terms[0].labels[0].title == "Part-of-speech")
{
result = true;
}
but it occured runtime error occasionly in following situation
i. m.terms == null
ii. m.terms != null, but m.terms[0] does not intialized.
iii. m.terms != null, and m.terms[0] has been exist but
m.terms[0].label does not initialized.
...
so i did modify it to like this:
if (m.terms[0] != null)
{
if (m.terms[0].labels != null)
{
if (m.terms[0].labels[0].title == "Part-of-speech") { result = true; }
}
}
is it the best way?
&& is a short circuiting operator, so the first way you wrote it and the second way will be functionally equivalent.
if (a && b && c)
{
// work
}
b will only be evaluated if a returns true. (Same goes for c).
In your code, checking m.terms[0].labels will not be a problem because you would have short-circuited out of the expression if m.terms[0] had been null.
To completely cover yourself, you'd want to possibly add checks for m and m.terms, however.
m != null && m.terms != null && m.terms.Count > 0 && m.terms[0] != null ...
As it evaluates from left to right, it will break on the first condition that doesn't pass and the rest will go unchecked.
int index = 0;
int labelIndex = 0;
string titleToCheck = "Part-of-speech";
if (m != null && m.terms != null && m.terms.Count > index)// or m.Length...
{
if (m.terms[index] != null && m.terms[index].labels != null &&
m.terms[index].labels.Count > labelIndex)
{
if (m.terms[index].labels[labelIndex].title == titleToCheck)
{
result = true;
}
}
}
This is all about readability. C# uses Short-circuit evaluation so in functionality there is no difference.
try this
if (m!=null && m.terms!= null && m.terms[0].labels!=null && m.terms[0].labels[0].title!=null && m.terms[0].labels[0].title == "Part-of-speech")
Yes, it would be better to split off each null check into a separate if statement.
The reason is that the second and third conditions require the first to not be null. If the first is null, then the second and third conditions will in turn throw errors because their parent is null yet is trying to be accessed.

Categories

Resources