if 문에서 상수 비교시 `x == 5` 대신 `x is 5`를 쓰는 것에 대한 생각 나눔

저는 C# 코딩에서 조건의 상수 비교시 x == 5 대신 x is 5를 쓰려고 요즘 노력하고 있습니다.
여기서 상수는 열거형도 포함인데요,

state == State.Start || state == State.Pause를,

state is State.Start or State.Pause로 쓰는 식입니다.

조사를 해보지는 않았지만, 컴파일러에게 좀 더 분기를 최적화 할 수 있는 힌트를 주기 때문에 속도면에서도 유리할 것 같은데요, 어떻게 생각하시나요?

4개의 좋아요

저는 조건식이 단항일 때는 기존 방식을 사용하고 복수일 경우 패턴 매칭을 사용하고 있습니다.

이건 습관 문제일텐데 특히 x is null 이 구문은 아직도 낯서네요… :thinking:

만약 성능상에 커다란 이점이 있다면 바꿀 수 있을 것 같긴 한데… 고민되네요.

2개의 좋아요

네. 맞아요. 단항일 때 굳이 is을 써야돼? 라는 내적 갈등이 저도 긴 시간동안 있었는데요,

그런데 패턴 매칭이 익숙해질 수록 기존 방식에 대한 조건비교가 점점 더 일관되게 느껴지지 않게 되면서… 이런 노력을 시작하게 되었습니다. 다음의 코드처럼 쓰기 위해서는 is를 반드시 써야 하기도 했고요.

if (object is not null userInfo)
   return;

Console.WriteLine(userInfo.Name);
3개의 좋아요

저도 is를 많이 쓰는 편인데, 아래와 같은 이유들 때문입니다.

우선, ==/!= 연산자나 Equals() 메서드 등과 달리 is 연산자는 재정의가 불가능하여 자료형에 따라 재정의되어 있을 수도 있다는 고려를 안 해도 됩니다. 프리미티브 타입에 대해서는 편하게 ==를 쓰기는 하지만, 여러 라이브러리에서 저마다 정의한 자료형들이나 여러 작업자가 협력하는 프로젝트의 경우 그 프로젝트 내에서 정의한 자료형까지, == 연산자를 어떻게 정의했을지 알 수 없을 때가 많기 때문에 == 대신 is를 쓰게 되는 것 같습니다. 특히 null 등에 대해 어떻게 동작하는지 구현을 열어봐야 알 수 있고, 그 구현조차도 나중에 업데이트되면서 동작이 바뀔 수 있다는 불안이 있습니다. (빌드가 깨지는 건 괜찮습니다. 빌드는 안 깨지는데 동작이 바뀔 수 있어서 불안합니다.)

반면, 그 자료형의 저자가 의도한 “같음”(equality)의 기준을 따르고 싶으면, 그 경우 역시도 == 연산자를 쓰지 않고 그냥 IEquatable<T> 인터페이스를 구현하는지 확인한 뒤 Equals() 메서드를 명시적으로 부르는 편입니다. 제가 자료형을 정의할 때 IEquatable<T> 인터페이스를 구현하는 경우, 사람들이 == 연산자를 무심코 쓴다는 것을 알기 때문에 ==/!= 연산자를 모두 구현하긴 하지만, 저 자신이 그 두 연산자를 잘 쓰지는 않는 것 같습니다. (제 맘대로 언어를 조금 고칠 수 있다면, object.Equals() 메서드를 아예 없애고 ==/!= 연산자는 IEquatable<T>.Equals() 구현을 한 자료형만 쓸 수 있게 만들고 싶습니다. :roll_eyes:)

또 다른 이유로는 앞서 @dimohy 님이 보여주신 예와 같이, is 연산자로 형 소거(type erasure)가 가능하기 때문입니다. 앞으로 C#도 F#처럼 대수적 자료형(algebraic data type)이나 닫힌 계통의 자료형을 선언할 수 있게 되면 패턴 매칭이 점점 더 유용해질 뿐만 아니라, 코딩할 때 피할 수 없게 될 것이라고 생각합니다. (실제로 상속 대신 대수적 자료형이 표준적인 추상화 도구인 함수형 언어에서는, 객체 지향 프로그래밍에서 서브타입 다형성을 피할 수 없는 것과 같이 패턴 매칭을 피할 수 없습니다.)

6개의 좋아요

옷. 그랬으면 참 좋겠는데… 이미 세월이 지나 하위호환을 위해 C# 설계자가 포기한 듯 합니다;

저도 동의합니다. 그리고 C#이 그렇게 변하고 있는 것 같고요. 의미 있는 댓글 감사합니다.

4개의 좋아요

저는 아직 습관을 버리지 못하고 있…

근데 is 를 쓰는 게 더 좋아보이긴 합니다.

기존의 사용 습관에 따르자면 is 는 타입에 대한 검사를 포함하니까요.
x is 5 는 x에 대해 반드시 int 라는 것을 함께 비교하도록 표현해주지요. 괜찮은 문법인 것 같습니다.
흡사 javascript 에서 x === 5 를 사용하는 것 같은 느낌이라 좋은 거 같아요. =ㅂ=b

근데 x is null 은 좀 아직도 손이 잘 안 갑니다.
이게 null 인지 여부보다는 null로 형변환이 가능한가… 라는 의미같아 보여서 (실제론 null 체크이지만…)
살짝 이런 코드를 만나면 흠칫 하기는 합니다.

근데 또 x is not null 또 이건 괜춘하더군요…

이 간사함이란… ~ㅁ~;;;

5개의 좋아요

같은 얘기는 아니지만 저도 null이라는 단어 자체를 안쓰고 싶어서 x is null에 거부감이 있었습니다. (x is not null은 신기하게 x가 널이 아닐 경우여서 그런지 거부감이 없었더랬죠 ㅎㅎ) 그런데 결국에는 내가 만든 코드가 null일 수 없다! 는 확신에 의해서인것 같아서… ㅎㅎ 계속해서 전환 중입니다.

참고로 .NET 6부터 느낌표(!)랑 물음표(?)를 통해 널값을 처리할 수 있는데요. 확신에 찬 것은 과감히 느낌표로 땻! 처리하면 됩니다;

Node.Parent!.Name // 부모가 없으면 이상한 자식이다.

4개의 좋아요