.Net 2+:if( 1 == null )이 더 이상 컴파일러 예외를 발생시키지 않는 이유는 무엇입니까?
-
09-06-2019 - |
문제
나는 사용하고있다 int
예를 들어 이는 .Net의 모든 값 유형에 적용됩니다.
.Net 1에서는 다음이 컴파일러 예외를 발생시킵니다.
int i = SomeFunctionThatReturnsInt();
if( i == null ) //compiler exception here
이제 (.Net 2 또는 3.5에서) 해당 예외가 사라졌습니다.
나는 이것이 왜인지 압니다:
int? j = null; //nullable int
if( i == j ) //this shouldn't throw an exception
문제는 그렇기 때문에 int?
nullable이고 int
이제 암시적 캐스트가 있습니다. int?
.위의 구문은 컴파일러 마법입니다.실제로 우리는 다음을 수행하고 있습니다.
Nullable<int> j = null; //nullable int
//compiler is smart enough to do this
if( (Nullable<int>) i == j)
//and not this
if( i == (int) j)
그럼 이제 우리가 할 때 i == null
우리는 다음을 얻습니다:
if( (Nullable<int>) i == null )
어쨌든 C#이 이를 계산하기 위해 컴파일러 논리를 수행하고 있다는 점을 고려하면 다음과 같은 절대값을 처리할 때 이를 수행하지 않을 만큼 똑똑할 수 없는 이유는 무엇입니까? null
?
해결책
이건 컴파일러 문제가 아닌거 같은데 그 자체로;정수 값은 결코 null이 아니지만 이를 동일시하는 아이디어는 유효하지 않습니다.항상 false를 반환하는 유효한 함수입니다.그리고 컴파일러는 알고 있습니다.코드
bool oneIsNull = 1 == null;
컴파일되지만 컴파일러 경고가 표시됩니다. The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'
.
따라서 컴파일러 오류를 다시 확인하려면 프로젝트 속성으로 이동하여 이 오류에 대해 '경고를 오류로 처리'를 설정하세요. 그러면 다시 빌드 중단 문제로 표시되기 시작합니다.
다른 팁
이상한 ....NET 3.5를 대상으로 VS2008로 이것을 컴파일:
static int F()
{
return 42;
}
static void Main(string[] args)
{
int i = F();
if (i == null)
{
}
}
컴파일러 경고가 표시됩니다.
warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'
그리고 다음 IL을 생성합니다.아마도 JIT는 최적화할 것입니다.
L_0001: call int32 ConsoleApplication1.Program::F()
L_0006: stloc.0
L_0007: ldc.i4.0
L_0008: ldc.i4.0
L_0009: ceq
L_000b: stloc.1
L_000c: br.s L_000e
코드 조각을 게시할 수 있나요?
컴파일러는 null을 허용하지 않는 유형을 null과 비교할 때 여전히 경고를 생성합니다. 이는 당연히 그래야 하는 방식입니다.경고 수준이 너무 낮거나 최근 버전에서 변경되었을 수 있습니다(.net 3.5에서만 해당).
2.0 프레임워크에서는 nullable 값 유형을 도입했습니다.리터럴 상수 "1"은 null이 될 수 없지만 이제 기본 유형(int)을 Nullable int 유형으로 캐스팅할 수 있습니다.내 생각엔 컴파일러가 더 이상 int 유형이 리터럴 상수인 경우에도 null을 허용하지 않는다고 가정할 수 없다는 것입니다.2.0을 컴파일할 때 경고가 나타납니다.
경고 1 'int' 유형의 값은 'int?' 유형의 'null'과 결코 같지 않으므로 표현식의 결과는 항상 'false'입니다.
경고는 새로운 것입니다(제 생각에는 3.5입니다). 오류는 제가 한 것과 동일합니다. 1 == 2
, 결코 사실이 아닌 것을 발견할 만큼 똑똑합니다.
나는 완전한 3.5 최적화를 사용하면 전체 진술이 제거될 것이라고 생각합니다. 이는 결코 진정한 평가가 아닌 매우 영리하기 때문입니다.
내가 원할 수도 있지만 1==2
컴파일하다 (예를 들어 다른 것을 테스트하는 동안 기능 블록을 끄기 위해) 원하지 않습니다 1==null
에게.
유형이 호환되지 않기 때문에(값 유형은 null이 될 수 없음) 컴파일 시간 오류여야 합니다.그렇지 않은 것이 참 안타깝습니다.