You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/csharp/language-reference/operators/null-conditional-operators.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ helpviewer_keywords:
8
8
- "?[] operator [C#]"
9
9
ms.assetid: 9c7b2c8f-a785-44ca-836c-407bfb6d27f5
10
10
---
11
-
# ?. and ?[] null-conditional operators (C# and Visual Basic)
11
+
# ?. and ?[] null-conditional operators (C# Reference)
12
12
13
13
Tests the value of the left-hand operand for null before performing a member access (`?.`) or index (`?[]`) operation; returns `null` if the left-hand operand evaluates to `null`.
Copy file name to clipboardExpand all lines: docs/visual-basic/language-reference/operators/null-conditional-operators.md
+47-11Lines changed: 47 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,14 +9,19 @@ helpviewer_keywords:
9
9
---
10
10
# ?. and ?() null-conditional operators (Visual Basic)
11
11
12
-
Tests the value of the left-hand operand for null (`Nothing`) before performing a member access (`?.`) or index (`?()`) operation; returns `Nothing` if the left-hand operand evaluates to `Nothing`. Note that, in the expressions that would ordinarily return value types, the null-conditional operator returns a <xref:System.Nullable%601>.
12
+
Tests the value of the left-hand operand for null (`Nothing`) before performing a member access (`?.`) or index (`?()`) operation; returns `Nothing` if the left-hand operand evaluates to `Nothing`. Note that in expressions that ordinarily return value types, the null-conditional operator returns a <xref:System.Nullable%601>.
13
13
14
14
These operators help you write less code to handle null checks, especially when descending into data structures. For example:
15
15
16
16
```vb
17
-
DimlengthAsInteger?=customers?.Length' Nothing if customers is Nothing
18
-
DimfirstAsCustomer=customers?(0)' Nothing if customers is Nothing
19
-
DimcountAsInteger?=customers?(0)?.Orders?.Count()' Nothing if customers, the first customer, or Orders is Nothing
17
+
' Nothing if customers is Nothing
18
+
DimlengthAsInteger?=customers?.Length
19
+
20
+
' Nothing if customers is Nothing
21
+
DimfirstAsCustomer=customers?(0)
22
+
23
+
' Nothing if customers, the first customer, or Orders is Nothing
24
+
DimcountAsInteger?=customers?(0)?.Orders?.Count()
20
25
```
21
26
22
27
For comparison, the alternative code for the first of these expressions without a null-conditional operator is:
@@ -28,27 +33,58 @@ If customers IsNot Nothing Then
28
33
EndIf
29
34
```
30
35
31
-
The null-conditional operators are short-circuiting. If one operation in a chain of conditional member access and index operations returns Nothing, the rest of the chain’s execution stops. In the following example, C(E) isn't evaluated if `A`, `B`, or `C` evaluates to Nothing.
36
+
The null-conditional operators are short-circuiting. If one operation in a chain of conditional member access and index operations returns `Nothing`, the rest of the chain’s execution stops. In the following example, `C(E)` isn't evaluated if `A`, `B`, or `C` evaluates to `Nothing`.
32
37
33
38
```vb
34
39
A?.B?.C?(E);
35
40
```
36
41
37
-
Another use for null-conditional member access is to invoke delegates in a thread-safe way with much less code. The old way requires code like the following:
42
+
Another use for null-conditional member access is to invoke delegates in a thread-safe way with much less code. The following example defines two types, a `NewsBroadcaster` and a `NewsReceiver`. News items are sent to the receiver by the `NewsBroadcaster.SendNews` delegate.
43
+
44
+
```vb
45
+
PublicModuleNewsBroadcaster
46
+
DimSendNewsAsAction(OfString)
47
+
48
+
PublicSubMain()
49
+
DimrecAsNewNewsReceiver()
50
+
Dimrec2AsNewNewsReceiver()
51
+
SendNews?.Invoke("Just in: A newsworthy item...")
52
+
EndSub
53
+
54
+
PublicSubRegister(clientAsAction(OfString))
55
+
SendNews=SendNews.Combine({SendNews,client})
56
+
EndSub
57
+
EndModule
58
+
59
+
PublicClassNewsReceiver
60
+
PublicSubNew()
61
+
NewsBroadcaster.Register(AddressOfMe.DisplayNews)
62
+
EndSub
63
+
64
+
PublicSubDisplayNews(newsItemAsString)
65
+
Console.WriteLine(newsItem)
66
+
EndSub
67
+
EndClass
68
+
```
69
+
70
+
If there are no elements in the `SendNews` invocation list, the `SendNews` delegate throws a <xref:System.NullReferenceException>. Before
71
+
null conditional operators, code like the following ensured that the delegate invocation list was not `Nothing`:
38
72
39
73
```vb
40
-
Dimhandler=AddressOf(Me.PropertyChanged)
41
-
IfhandlerIsNotNothing
42
-
Callhandler(…)
74
+
SendNews=SendNews.Combine({SendNews,client})
75
+
IfSendNewsIsNotNothingThen
76
+
SendNews("Just in...")
77
+
EndIf
43
78
```
44
79
45
80
The new way is much simpler:
46
81
47
82
```vb
48
-
PropertyChanged?.Invoke(…)
83
+
SendNews=SendNews.Combine({SendNews,client})
84
+
SendNews?.Invoke("Just in...")
49
85
```
50
86
51
-
The new way is thread-safe because the compiler generates code to evaluate `PropertyChanged` one time only, keeping the result in a temporary variable. You need to explicitly call the `Invoke` method because there is no null-conditional delegate invocation syntax `PropertyChanged?(e)`.
87
+
The new way is thread-safe because the compiler generates code to evaluate `SendNews` one time only, keeping the result in a temporary variable. You need to explicitly call the `Invoke` method because there is no null-conditional delegate invocation syntax `SendNews?(String)`.
0 commit comments