?. 및 ?() null 조건부 연산자(Visual Basic)

멤버 액세스(?.) 또는 인덱스(?()) 작업을 수행하기 전에 Null(Nothing)에서 왼쪽 피연산자의 값을 테스트합니다. 왼쪽 피연산자가 Nothing으로 계산하는 경우 Nothing을 반환합니다. 일반적으로 값 형식을 반환하는 식에서 null 조건부 연산자는 Nullable<T>를 반환합니다.

이러한 연산자는 null 검사의 처리를 위해 작성하는 코드의 양을 줄이는 데 도움이 되며 특히 데이터 구조에서 아래로 내려가는 경우에 유용합니다. 예시:

' Nothing if customers is Nothing
Dim length As Integer? = customers?.Length

' Nothing if customers is Nothing
Dim first As Customer = customers?(0)

' Nothing if customers, the first customer, or Orders is Nothing
Dim count As Integer? = customers?(0)?.Orders?.Count()

비교를 위해 null 조건부 연산자가 없는 첫 번째 식에 대한 대체 코드는 다음과 같습니다.

Dim length As Integer?
If customers IsNot Nothing Then
   length = customers.Length
Else
    length = Nothing
End If

해당 개체의 부울 멤버 값을 기반으로 null일 수 있는 개체에 대해 작업을 수행해야 하는 경우가 있습니다(예: 다음 예의 부울 속성 IsAllowedFreeShipping).

Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.

If customer IsNot Nothing AndAlso customer.IsAllowedFreeShipping Then
  ApplyFreeShippingToOrders(customer)
End If

다음과 같이 null 조건부 연산자를 사용하면 코드를 단축하고 수동으로 null 확인을 피할 수 있습니다.

Dim customer = FindCustomerByID(123) 'customer will be Nothing if not found.

If customer?.IsAllowedFreeShipping Then ApplyFreeShippingToOrders(customer)

Null 조건부 연산자는 단락 연산자입니다. 조건부 멤버 액세스 및 인덱스 작업 체인의 한 작업에서 Nothing을 반환하면 체인 실행의 나머지 부분이 중지됩니다. 다음 예에서 A, B 또는 CNothing으로 평가되는 경우 C(E)는 평가되지 않습니다.

A?.B?.C?(E)

Not someStr?.Contains("some string") 또는 Boolean?으로 평가되는 다른 값이 nothing 또는 HasValue=false 값을 갖는 경우 else 블록이 실행됩니다. 평가는 null/nothing이 다른 null/nothing과 동일하지 않은 SQL 평가를 따릅니다.

null 조건부 멤버 액세스의 또 다른 용도는 훨씬 적은 코드를 사용하여 스레드로부터 안전한 방식으로 대리자를 호출하는 것입니다. 다음 예에서는 NewsBroadcasterNewsReceiver라는 두 가지 형식을 정의합니다. 뉴스 항목은 NewsBroadcaster.SendNews 대리자에 의해 수신자에게 전송됩니다.

Public Module NewsBroadcaster
   Dim SendNews As Action(Of String)

   Public Sub Main()
      Dim rec As New NewsReceiver()
      Dim rec2 As New NewsReceiver()
      SendNews?.Invoke("Just in: A newsworthy item...")
   End Sub

   Public Sub Register(client As Action(Of String))
      SendNews = SendNews.Combine({SendNews, client})
   End Sub
End Module

Public Class NewsReceiver
   Public Sub New()
      NewsBroadcaster.Register(AddressOf Me.DisplayNews)
   End Sub

   Public Sub DisplayNews(newsItem As String)
      Console.WriteLine(newsItem)
   End Sub
End Class

SendNews 호출 목록에 요소가 없으면 SendNews 대리자가 NullReferenceException을 throw합니다. null 조건부 연산자 이전에는 다음과 같은 코드를 사용하여 대리자 호출 목록이 Nothing이 아닌지 확인했습니다.

SendNews = SendNews.Combine({SendNews, client})
If SendNews IsNot Nothing Then
   SendNews("Just in...")
End If

새로운 방식은 훨씬 더 간단합니다.

SendNews = SendNews.Combine({SendNews, client})
SendNews?.Invoke("Just in...")

새로운 방식은 컴파일러가 SendNews를 한 번만 평가하는 코드를 생성하고 결과를 임시 변수에 유지하기 때문에 스레드로부터 안전합니다. null 조건부 대리자 호출 구문 SendNews?(String)가 없기 때문에 Invoke 메서드를 명시적으로 호출해야 합니다.

참고 항목