C#

C# ?. 와 ?[] 와 ?? 그리고 ??= 연산자 로 코드를 간결하게.

DragonTory 2022. 11. 16. 15:08
반응형

C# 에서 

if( A != null ) 

을 대체 할 문법으로 ?. ( null 조건부 연산자 )를 사용 하면

코드를 간결 하고 직관적으로 바꿀 수 있습니다.

 

?.  : Null 조건부 연산자

  ?. 앞의 구문이  null이 아닌지 판단 하여 null이 아니면 다음 구문을 실행 하는 연산자 입니다. 

A?.B?.Do(C);

와 같이 사용 하면 되는데 

만약

A== null :  ? 물음표 앞의 A 값이 null이 아니면 뒤따라 나오는 멤버 또는 식을 실행 시켜줍니다. 

A != null : A값이  null이 아니므로 뛰따라 오는 구문을 실행.

 그리고 B?. 을 실행 하고 평가 하게 되는데 

여기서 또 ?. 구문을 만나 A.B의 값이 null인지 아닌지 판단.

B가 null 아니면 최종 A.B.Do(C)를 실행 하게 됩니다.

결국, A또는 B 둘중에 하나라고 null이면 Do(C)는 실행 되지 않게 됩니다. 

 

?[ ]  :  조건부 인덱서

int[] A = new int[4] { 0,1,2,3 };
int value = A?[2] ?? 0;

위의 예제와 같이 A값이 null이면 null를 리턴 하고 

A값이 null이 아닌 값이라면 다음의 배열 요소를 리턴 하게 해주는 연산자 입니다.

?? 연산자는 아래에 설명 된 것 처럼 좌측의 구문이 null의 값이라면 우측의 값을 리턴 해 주는 null 병합 연산자 입니다.

따라서, 

A == null : 이 경우 value = 0; 이 됩니다.

A != null :  이 경우 value = A[2]; 가 됩니다.

 

?? : null 병합 연산자

?? 연산자의 좌측 구문의 값이 null이 아니라면 왼쪽의 값을 리턴,

좌측의 값이 null이라면 우측의 지정된 값을 리턴 하게 됩니다. 

int GetSumOfFirstTwoOrDefault(int[] numbers)
{
    if ((numbers?.Length ?? 0) < 2)
    {
        return 0;
    }
    return numbers[0] + numbers[1];
}

위의 예에서 보면 

numbers == null : 이 경우 ??의 좌측 구문은 null을 리턴 하고 값이 null이므로 우측의 0값이 결과로 리턴 됩니다. 

if( (0) > 2) 

numbers != null :   이 경우  if ((numbers.Length ) < 2) 의 형태가 됩니다. 

?? : null 병합 할당 연산자

?? 의 좌측의 값을 평가 하여 null이면 우측의 값을 좌측의 값에 할당 해 줍니다. 

마치 += 과 같은 형태 입니다 

List<int> numbers = null;
(numbers ??= new List<int>()).Add(5);

위의 예에서 보면 

numbers == null : 이 경우 numbers = new List(); numbers.Add(5); 와 같이

List를 새로 할 당 하고 리스트에 요소를 추가 합니다. 

numbers != null : 이 경우 numbers.Add(5); 와 같이 작동 되게 됩니다. 

 

위와 같이 ?. ?[] ?? ??= 연산자를 조합 하여 잘 사용 하면

if 문의 사용을 줄여서 코드를 간결 하게 작성 할 수 있습니다. 

 

사용 예제)

public class Sample
{
	static Sample _instance;
	public static Sample Instance => _instance ??= new();

	Action ActionChanged;
	public void OnClicked()
	{
		ActionChanged?.Invoke();
	}

	TextMeshProUGUI[,] CellList;    
	public string this[int row, int column]
	{        
		get => CellList?[row, column]?.text ?? string.Empty;
		set => CellList?[row, column]?.SetText ( value );        
	}
    
	Button Button;
	void Awake()
	{
		Button?.onClick.AddListener(OnClicked);
	}
}

 

반응형