본문 바로가기
C#

C# - 물음표 연산자(?, ??), 삼항연산자

by 개발 그리고 게발 2021. 7. 28.
728x90

코드를 작성할 때 null 처리와 단순 if else 조건을 처리할 때 '단순한 조건때문에 줄을 더 써야하나?' 라고 생각할 수 있습니다.

아주 간단한 조건인데도 불구하고 한줄로 쓸 수 있는 코드에 4줄이상 쓰게되면 줄수만 차지할 뿐입니다.

 

이런문제를 해결할 수 있는 방법으로 물음표 연산자를 사용할 수 있습니다.

물음표를 이용해서 if else조건, 특정 데이터타입의 속성을 읽어올 때, null에러 방지처리 와 같은 방법들이 있습니다.

 

 

 


? 기본 처리 방법

object tmp = {조건} ? {참(true)일 경우 return값} : {거짓(false)일 경우 return값}

 

?? 기본 처리 방법

object tmp = null;
object result = tmp ?? {tmp가 null일 경우 result에 return값}

 


 

 

 

if / else 조건 간단처리

if else조건으로 코드를 작성할 때 조건이 간단하다면 ? 하나로 간단하게 코드를 작성할 수 있습니다.

 

기본 if else

 

 

string food = "Kimbap";
string store = "";

if (food == "Kimbap")
{
	store = "Kimgane";
}
else
{
	store = "No Store";
}

 

 

 

물음표 연산자(?)

 

굳이 if / else 코드를 넣지않고 변수에 바로 조건을 넣어 값을 할당하기 때문에 코드 수를 줄일 수 있습니다.

string food = "Kimbap";
string store = food == "Kimbap" ? "Kimgane" : "No Store";

// 결과 : Kimgane

 

또한 if문의 () 안에 넣는 조건처럼 아래와 같이 여러조건을 붙일 수도 있습니다

string food = "Kimbap";
string store = (food == "Kimbap" && food.IndexOf("K") > -1 && food.Length == 6) ? "Kimgane" : "No Store";

// 결과 : Kimgane

 

 

 

 

물음표 연산자(?)의 지양되는 처리방식

한줄에 쓰기위해 물음표 연산자 조건을 더 깊게 처리하는 경우에는 오히려 코드 가독성에 악영향을 줍니다.

모아니면 도 식의 처리에만 가급적 물음표 연산자를 이용하는 것이 바람직하며 아래와 같은 방법은 안쓰길 권장합니다.

 

한줄식

// 결과 : Not start S
string result = text == "Food" ? (text.StartsWith("S") ? "Start S" : "Not start S") : "Not Food";

 

if / else를 이용해서 풀 경우

// 결과 : Not Start S
string text = "Food";
string result = "";

if (text == "Food")
{
	if (text.StartsWith("S"))
	{
		result = "Start S";
	}
	else
	{
		result = "Not Start S";
	}
}
else
{
	result = "Not Food";
}

 



데이터 타입의 속성을 읽어올 경우

 

아래와 같은 DataTable이 있다고 할 경우 Count를 가져오려고 할 때, Api통신이 끊기거나 기타 문제가 생겨서 결과값이 null로 받을 때 다음과 같이 처리하게 됩니다.

 

DataTable data = // Api통신 함수;

if (data != null && data.Rows.Count > 0)
{
	// data소스 처리
}

 

하지만 물음표 연산자를 사용하면 data가 null일 경우에만 이후의 Row, Count속성을 가져오기 때문에 아래와 같이 코드를 줄여서 사용할 수 있습니다.

이 방법은 Dictionary, HashTable 등 다른 데이터타입들의 속성값을 가져올 때도 유용하게 처리할 수 있습니다.

 

DataTable data = // Api통신 함수;

if (data?.Rows.Count > 0)
{
	// data소스 처리
}

 

data.Rows.Count를 가져올 때 물음표 연산자를 이용해서 변수로 받는다면 null이 가능하도록 변수를 받아야 하는데 아래와 같이 변수를 받아야 합니다

// DataType 뒤에 ?을 붙일 경우 null로도 받을 수 있는 DataType으로 됨
int? cnt = data?.Rows.Count

 

int?는 null 혹은 숫자를 받을 수 있는 데이터 타입이지만 int는 숫자만 가능한 데이터 타입이기 때문에 아래와 같은방법으로 하게되면 컴파일 에러가 발생합니다.

(data가 null 일 수 있기 때문에 null을 return해도 받을 수 있는 데이터 타입을 사용해야함)

// data?.Rows.Count는 null 혹은 숫자를 return하는데 int는 null을 받을 수 없어서 컴파일에러 발생
int cnt = data?.Rows.Count

 

 

 

더블 물음표 연산자(??)

 

변수처리

 

어떠한 값이 null 일경우 대체할 값을 입력합니다

// Empty를 return
string null_obj = null;
string result = null_obj ?? "Empty";

// Not Empty를 return
string string_txt = "Not Empty";
string result2 = string_txt ?? "Empty";

 

함수 파라미터 처리

 

어떠한 함수에 Null Reference Exception이 발생할 위험을 줄입니다.

 

아래와 같은 경우에 cnt값을 구하려고 하는데 lst가 null로 오는 케이스에서는 Null Reference Exception이 발생합니다.

public void RunTestCode()
{
	List<string> lst = null;

	GetValue("Text", lst);
}

public void GetValue(string text, List<string> tmp_lst)
{
	// tmp_lst가 Null이기 때문에 Null Reference Exception이 발생
	int cnt = tmp_lst.Count;
}

 

 

고의적으로 null을 넣지않겠지만, null이 올 수도 있는 위험성을 줄이기 위해서는 다음과 같은 코드로 활용할 수 있습니다.

 

public void RunTestCode()
{
	List<string> lst = null;

	// lst이 null이 될 경우 new List<string>()을 넣어줘서 null 참조에러를 방지합니다.
	GetValue("Text", lst ?? new List<string>());
}

public void GetValue(string text, List<string> tmp_lst)
{
	int cnt = tmp_lst.Count;
}

 

728x90

댓글