null이 주어지면 is 연산자가 왜 false를 반환합니까?


135

is연산자가 약간 일치하지 않는 것 같습니다 .

bool Test()
{
    // Returns false, but should return true.
    return null is string;
}

null값이 참조 (또는 널 입력 가능) 유형에 속할 것으로 예상합니다 . 실제로 C # 언어 사양은이 가설을 지원하는 내용을 말합니다 (6.1.6 암시 적 참조 변환).

암시 적 참조 변환은 다음과 같습니다.
...
• null 리터럴에서 모든 참조 유형으로.

의 설명 (7.10.10는 IS 연산자) is표현식이 말하는하여 운영자 시작 (E is T)에서 참조 변환 할 때 진정한 발생합니다 E을이 T존재하지만 저자가 때 명시하는 경우를 제외하여 갈 E은 IS null문자 또는이 null값을 .

왜 그렇게합니까? 나에게는 그것은 직관이 아닌 것 같습니다.


프로그래머가 null을 명시 적으로 제외 한 이유는 최고의 질문입니다.
Miserable Variable

2
가까운 투표를 철회 할 수는 없지만 다음 질문은 괜찮습니다. meta.stackexchange.com/questions/36850/…
Merlyn Morgan-Graham

자바에서 null typeof Object거짓을 반환
래칫 괴물 23

그 가정 null is string했다 true, 이것은 그 암시 null입니다 string. 또한 가정 null is Nullable<int>true것을 의미하는 것은, nullA는 Nullable<int>. 이제이 질문에 대답하십시오 : 어떤 유형 null입니까?
CVn

1
@ 마이클 Kjörling : 비 sequitur. 언급 된 사실 (null은 문자열, null은 Nullable <int>)에서 그 질문에 대답 할 수 있어야합니다.
Gebb

답변:


195

이 질문은 2013 년 5 월 30 일에 제 블로그주제였습니다 . 좋은 질문 감사합니다!


당신은 빈 차도를 쳐다보고 있습니다.

누군가가 "차도에 혼다 시빅을 탈 수 있습니까?"라고 묻습니다.

예. 예, 그럴 수 있습니다.

누군가 두 번째 차도를 가리 킵니다. 또한 비어 있습니다. "내 차도의 현재 내용이 차도에 맞을 수 있습니까?"

그렇습니다. 두 차도 모두 비어 있습니다! 따라서 처음에는 내용이 없기 때문에 한 내용이 다른 내용에 잘 맞을 수 있습니다.

"차도에 혼다 시빅이 포함되어 있습니까?"

아니 그렇지 않아.

is연산자가 두 번째 질문에 대답 한다고 생각합니다 . 이 값이 주어진다면 해당 유형의 변수에 적합합니까? 널 참조가이 유형의 변수에 적합합니까? 그렇습니다.

그것은 is운영자가 대답 하는 질문이 아닙니다 . 것을 질문 is연산자는 응답은 세 번째 질문입니다. y is X요구하지 않는 것은 " y유형의 변수의 유효한 값 X? "그것은 "묻습니다 인가 y형식의 개체에 대한 유효한 참조 X? "널 참조가 유효한 참조하지 않기 때문에 어떠한 의 목적 어떤 종류, 대답은 '노'입니다 ". 그 차도는 비어 있습니다. 혼다 시빅이 포함되어 있지 않습니다.

그것을 보는 또 다른 방법은 y is X"내가 말하면 y as X, 널이 아닌 결과를 얻을 것인가?"라는 질문에 대답하는 것입니다.


질문을 좀 더 깊이 살펴 보려면 :

null 값은 참조 (또는 nullable) 유형에 속할 것으로 예상합니다.

하나는 암시 적으로 가정 될 타입 A는 값들의 세트 및 그 할당 호환 형 X의 변수 값 (Y)의하면 아무 이상도 이하이고 , y는 집합 X의 멤버인지 여부를 확인 .

이것이 형식을 보는 매우 일반적인 방법이지만 형식을 보는 유일한 방법은 아니며 C #이 형식을 보는 방법도 아닙니다. 널 참조는 C #에서 유형이없는 멤버입니다. 할당 호환성 은 단순히 집합에 값이 포함되어 있는지 확인하는 것이 아닙니다 . 널 참조가 참조 유형 X의 변수와 호환 가능한 대입 이라고해서 널이 X 유형의 멤버라는 의미는 아닙니다. "대입이 호환 가능"관계이고 "유형의 멤버"관계는 분명히 중복되지만 CLR에서는 동일하지 않습니다.

유형 이론에 대한 생각이 당신에게 관심이 있다면, 주제에 관한 최근 기사를 확인하십시오.

이것을 "유형"이라고 부르는 것은 무엇입니까? 1 부

이것을 "유형"이라고 부르는 것은 무엇입니까? 두 번째 부분


@Gebb : 기꺼이 도와 드리겠습니다. 이 문서는 당신에게 관심의 대상이 될 수 있습니다 : blogs.msdn.com/b/ericlippert/archive/2010/09/16/...
에릭 Lippert의

Eric은 이것을 블로그 게시물로 바꿨
Kevin Cathcart

y is X" y유형 변수의 유효한 값은 X?" " y유형의 객체에 대한 유효한 참조 X입니까?" 그게 요점입니다! 감사!
잘랄

하지만 내가 묻는다면 y is int? 보면 "당신의 차도에 혼다 시민이 포함되어 있습니까?"라고 묻습니다. 차도가 비어 있는데 왜 대답이 '아니요'입니까? 후드 아래를 보면 "차도에 혼다 시빅이 있습니까? 아니면 혼다 시빅이 없습니다"라는 표지판이 있습니까? 차도에 표지판이 있다고해도 대답은 여전히 ​​아니오입니다.
팩스

1
@ Gerard : 사람들이 길고, 장황하고, 수다스러운 대답을하면 사람들은 더 짧아야한다고 말하고 간결하게 말하면 간결한 대답은 사람들이 더 길어야한다고 말합니다. 제 결론은 사람들이 불평하는 것을 좋아한다는 것입니다. 이 8 살짜리 질문에 대한 답이 무엇인지에 대한 느낌이 있기 때문에, 스스로 대답함으로써 좋은 답을 만드는 것이 무엇인지 보여 주면 배울 수 있습니다.
Eric Lippert

24

나는 null is string거짓을 돌려주는 것이 매우 직관적 이라고 생각 합니다. Null은 아무 의미가 없으며 문자열이 아닙니다. 따라서 false를 반환해야합니다. 언어 디자이너가 선택한 선택이지만 실제 세계의 의미를 고려할 때 매우 직관적입니다.


2
+1은 OP가 이미 알고있는 사양에 의문을 제기하지 않고 직관적인지 여부에 관한 것이기 때문입니다. 당신이 영어 문장으로 요구하는 경우에 "입니다 null다른 대답은 '그렇지, 아니오, 문자열" "입니다 null에 할당 string"
Davy8

null is string(string)null is stringC #에서 null 참조가 작동하는 방식에 익숙하지 않은 경우 매우 직관적이며 일시 중지가 필요할 수 있습니다.
decPL

24

null문자가 할당 될 수있는 임의의 참조 유형. 그 자체로는 유형 이 아닙니다 . 널 참조 를 나타내는 특수 리터럴 입니다 .

전달 될 때 is반환 되는 경우 리터럴 로 무엇을 할 수 있습니까? 아무것도 아닙니다 . 혼란스러운 문제를 제외하고는 돌아 오는 시점은 무엇입니까 ?truenullnullnulltrue


어쨌든-직관적 인 측면에서 영어로 코드를 읽고 나에게 알려주십시오.

null is string;

내가 그것을 볼 때, 그것은 질문을하는 것 같습니다 is "nothing" a string?. 내 직감은 그렇지 않다고 말해줍니다 nothing.


괜찮습니다.하지만 문자열이기도합니다. 그런데 왜 (null is string)돌아온다는 걸까요?
Gebb

나는 다른 방향으로 그것을 말했을 것입니다. 모든 참조 유형은 null 일 수 있습니다. null은 단지 null입니다.
Mark H

@Oded 그래서 null 값은 객체 유형의 유효한 값입니까? 이 유형의 변수에 할당 할 수 있습니까? 답은 '예'인 것 같습니다. 값이 완벽하게 유효합니다. 제 생각에는 (null is object)표현식이 정확하게 확인해야한다는 것입니다.
Gebb

@Gebb : ValueTypes도 객체이지만 참조 유형이 아니라는 것을 잊지 마십시오.
Mark H

1
@Oded : "혼란스러운 문제를 제외하고는 그것이 어떻게 되풀이 되는가?" 실제로는 언어를보다 논리적으로 만듭니다. 다음 두 가지 사항을 고려하십시오. (1) is연산자는 참조 (여기서는 다른 유형의 변환이 필요하지 않음) 변환이 있는지 확인합니다. (2) null는 모든 참조 유형으로 변환 할 수 있습니다. 따라서 (null is T)T가 참조 유형이면 true를 반환해야합니다. 그러나 아닙니다. 여기에는 명백한 예외가 있습니다.
Gebb

12

http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx

다음 조건이 모두 충족되면 is 표현식은 true로 평가됩니다.

  • expression이 널이 아닙니다.
  • 표현식을 유형으로 캐스트 할 수 있습니다. 즉, 예외를 던지지 않고 형식 (표현식)의 캐스트 표현식이 완료됩니다. 자세한 내용은 7.6.6 캐스트 표현식을 참조하십시오.

1
어쨌든 문서는 expression이 null 일 수 없으며 (이미 알고 있음) 그 이유를 알려주지 않습니다.
username

왜 다른 방법으로 원하십니까?
비참한 변수

1
@username :이 답변은 기계적으로 작동하는 방식을 설명하고 참조 할 수있는 모델을 제공합니다. 여기서 우주의 의미를 묻습니다. 난 당신이 운이 좋은 것 같아요 우리의 신에 자주 SO)
Merlyn 모건 - 그레이엄

10

실질적으로 "null is T == false"를 사용하면 추가 코드를 입력하지 않아도됩니다.

말하지 말고

if (X != null && X is Foo) {}

그냥 말할 수 있어요

if (X is Foo) {}

그리고 그것으로 끝납니다.


8

null

나는 이것이 문제의 핵심에 도달하는 것처럼 보이기 때문에 귀하의 질문에서 이것을 인용했습니다. 가치 null 가 아닙니다 -가치 가 없습니다 . is나에게 의 목적은 질문에 대답하는 것 같습니다.

에 캐스팅 E하면 T성공적으로 T?

지금, 당신은 동안 캐스트 nullT 오류없이 당신이 그렇게 후 하지 않는다 "는 없습니다 T당신이 아직도있어 아무것도 -"를. 따라서 null"is"는 T그렇지 않으므로 isfalse를 반환합니다.


3

Java에는 정확히 같은 일을하는 연산자가 있지만 훨씬 긴 이름을 갖습니다 instanceof. null instanceof Stringnull은 a의 인스턴스가 아니기 때문에 false 를 반환 하는 것은 매우 직관적 String입니다. 따라서 사용할 때null Java 버전을 좀 더 직관적입니다.

그러나이 두 연산자는 전체 계층 구조를 살펴볼 때도 true를 반환합니다. 예 : 의 인스턴스가있는 경우 String입니다 Object. 그리고 여기가 이제와 C # (인스턴스가 실제로 하나, 매우 특정 유형이 있기 때문에)의 덜 직관적 인 비트 것이 자바의 is(모든이 있기 때문에 더 직관적 String 이다Object 깊은 내부).

결론 : 한 마디로 꽤 진보 된 논리를 묘사하려고하면이 방법으로 다른 사람들을 혼란스럽게 할 수밖에 없습니다. 대부분의 사람들은 하나의 의미에 동의 한 것으로 보이며 동의하지 않은 사람들은 조정해야했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.