New C#/VB – first asymmetry in conditions introduced?

119 Views Asked by At

C# guys will excuse me for VB, but the following should be related to both languages. EDIT: It is related but no-one noticed so far that C# and VB evaluate differently. Question adjusted.

Before, if we had simple

If condition Then
    ThenPart()
Else
    ElsePart()
End If

and wanted to re-arrange it into reverse order, we swapped ThenPart() and ElsePart() and negated the condition (generally speaking, by using Not(condition)). It was possible to re-arrange every condition.

Recently, great Null-conditional Operators were introduced. And with them assymetry came into conditions. You can no longer use Not(condition) with them. Or am I overlooking something? (This is the question.)

Try re-arranging ThenPart() and ElsePart() into reverse order here:

Dim list As List(Of Integer) = Nothing
If list?.Count > 0 Then
    ThenPart()
Else
    ElsePart()
End If

The trick is that null value appears in condition and of course, it cannot be negated using Not. Therefore you cannot use trivial negation If Not(list?.Count = 0) nor you can use If list?.Count <= 0.

The only way is old-fashioned If list Is Nothing OrElse list.Count = 0. (Exact negation would use <= 0) (Edit: Applies only to VB. VB and C# diverge here, see below.)

Trivial times where it was simple to negate every operator are gone (edit: only in VB). Or am I overlooking something?


After additional research:

It looks in the C# you can safely do !(list?.Count = 0) and after this finding, C# got out of this question. No asymmetry here, you can negate as before. But as far as I can see, the asymmetry remains with VB because of null evaluation in Visual Basic which is similar to ANSI SQL – null value propagates through the expression. So in VB, you cannot negate list?.Count > 0 more trivially than If list Is Nothing OrElse list.Count = 0. (That's why I used word 'asymmetry'.) Or am I overlooking something?

2

There are 2 best solutions below

0
On BEST ANSWER

Trivial times where it was simple to negate every operator are gone.

Nothing has changed - if condition could return null in your first example then you could not simply swap the if and else parts. Adding null to the mix prevents simply using Not regardless of the new operator.

It's not the fault of the operator - it's the fact that a nullable boolean is not symmetric.

8
On

You should be able to negate condition just fine:

 if (!(list?.Count > 0))...

But there is no short form for negated one (you have to live with expanded form).

There is nothing new in relation to moving negation into condition (except you got shorter way of writing x != null && x.Count > 0 as x?.Count > 0) - same Morgan laws apply to negate.

Original condition (A and B):

 list != null && list.Count > 0 

Negated (not A or not B):

 list == null || list.Count <= 0

Note that similar behavior exist in C# 5 for nullable values - if you negate just operation (like > to <=) you get wrong results:

int? v = null;
Console.WriteLine(v1 > 1); // false
Console.WriteLine(!(v1 > 1)); // negated, so true
Console.WriteLine(v1 <= 1); // just > negated - false.