프로젝트를 진행하며 신기한 연산자를 발견했다.
C# 에서 만든 연산자인데 역시 Microsoft인가 언어가 정말 끊임없이 발전하는 것 같다.
먼저 !에 대해 설명할 것인데 !연산자라고 하면 흔히 아는 bool 값 앞에 !을 넣어 부정하는 논리 부정 연산자를 생각 할 수 있다. 하지만 내가 지금 설명할 것은 단항 후위 !연산자이다. 이렇게 장황하게 서술했지만 실상은 간단하다.
이름 그대로
null이 아니라고 명시해준다. (억제)
즉CS8625경고를 지워준다.
솔직히 굳이 사용해야 싶기도 하고 이런 쪽 개발도 아니라 잘 사용처는 모르겠다.
자세한 내용은 아래 링크를 보면 될 것이다.
! (null-forgiving) 연산자(C# 참조)
이 연산자의 나 같은 경우 개발을 하면서 많이 사용해 본적이 있다.
이 연산자 또한 개념은 간단하다.
피연산자가
null일 경우null을 반환하는 것이다.
C# : a가null로 평가되면 a?.x 또는 a?[x]의 결과는null입니다.
자세한 내용
Null 조건부 연산자 ?. 및 ?[] (C#)
이 연산자들 또한 개념은 간단하다. 위에서 학습한 결과를 토대로 어느정도 예측 할 수 있을 것이다. 바로 설명해 보겠다.
?? 연사자는 왼쪽부터
null이 아닐 경우 왼쪽 피연산자를 반환한다.
만약에null일 경우에는 오른쪽 연산자 평가하고 반환한다.
코드로 보면 이해하기 편할 것이다.
a = b ?? c;
| 왼쪽 피연산자(b) | 오른쪽 피연산자(c) | 반환값 |
|---|---|---|
| O | null | 왼쪽 값(b) |
| null | O | 오른쪽 값(c) |
개념은 위 연산자와 비슷하다.
왼쪽 피연산자가
null일 경우 오른쪽 피연산자를 값에 할당한다.
a ??= b;
나는 null 병합 대입 연산자를 싱글톤 패턴을 만들때 쓴적이 있는데
아래와 같이 썼다.
instance ??= this; // instance가 null이면 this를 할당
문득 아래 코드와 뭐가 다른지 궁금해져 속도를 비교해 보기로 하였다.
if(instance == null)
{
instance = this;
}
먼저 ??=연산자로 실행해 보겠다.
using System.Diagnostics;
static void Main(string[] args)
{
long startTime, endTime;
Test t1 = null;
Stopwatch watch = new Stopwatch();
watch.Start();
startTime = watch.ElapsedTicks;
for(int i = 0; i < 100; ++i)
{
t1 = null;
t1 ??= new Test();
}
endTime = watch.ElapsedTicks;
watch.Stop();
Console.WriteLine($"{String.Format("{0:#,###.###} ns", (1000 * 1000 * 1000 * (endTime - startTime) / Stopwatch.Frequency))}");
}
| 테스트 케이스 | 소요 시간 |
|---|---|
| 1 | 83,000 ns |
| 2 | 86,200 ns |
| 3 | 78,500 ns |
| 4 | 79,400 ns |
| 5 | 85,700 ns |
사양에 따라 보통 7~80,000 ns 를 보이고 있다.
이제 for문 안쪽 내용을 바꿔서 해보겠다.
| 테스트 케이스 | 소요 시간 |
|---|---|
| 1 | 84,700 ns |
| 2 | 83,000 ns |
| 3 | 82,000 ns |
| 4 | 87,200 ns |
| 5 | 76,300 ns |
어느정도 예상했지만 그냥 차이가 없는 수준이다.
그나마 ??= 연산자의 장점이라면 코드가 한줄이 된 정도?
그냥 자기 취향대로 쓰면 될 것같다.