[c#] 값 유형을 null과 비교해도 괜찮은 C #
나는 오늘 이것을 만났고 C # 컴파일러가 오류를 던지지 않는 이유를 모릅니다.
Int32 x = 1;
if (x == null)
{
Console.WriteLine("What the?");
}
x가 어떻게 null이 될 수 있는지 혼란 스럽습니다. 특히이 할당은 확실히 컴파일러 오류를 던지기 때문에 :
Int32 x = null;
x가 null이 될 수 있습니까? Microsoft가이 검사를 컴파일러에 넣지 않기로 결정 했습니까, 아니면 완전히 놓쳤습니까?
업데이트 :이 기사를 작성하기 위해 코드를 엉망으로 만든 후 갑자기 컴파일러가 표현식이 사실이 될 수 없다는 경고를 내보냈습니다. 이제 나는 정말 길을 잃었습니다. 나는 객체를 클래스에 넣었고 이제 경고는 사라졌지 만 질문이 남았습니다. 값 유형이 null이 될 수 있습니까?
public class Test
{
public DateTime ADate = DateTime.Now;
public Test ()
{
Test test = new Test();
if (test.ADate == null)
{
Console.WriteLine("What the?");
}
}
}
답변
연산자 과부하 해결에는 선택할 수있는 고유 한 최상의 연산자가 있기 때문에 이는 합법적입니다. 두 개의 nullable int를 취하는 == 연산자가 있습니다. int local은 nullable int로 변환 할 수 있습니다. null 리터럴은 nullable int로 변환 할 수 있습니다. 따라서 이것은 == 연산자의 합법적 인 사용이며 항상 거짓이됩니다.
마찬가지로, “if (x == 12.6)”이라고 말하면 항상 거짓이됩니다. int local은 double로 변환 가능하고 리터럴은 double로 변환 가능하며 분명히 같지 않을 것입니다.
답변
( int?
) 변환 이 있기 때문에 오류가 아닙니다 . 주어진 예에서 경고를 생성합니다.
‘int’유형의 값이 ‘int?’유형의 ‘null’과 같지 않기 때문에 표현식의 결과는 항상 ‘false’입니다.
IL을 확인하면 도달 할 수없는 분기가 완전히 제거 되었음을 알 수 있습니다. 릴리스 빌드에는 존재하지 않습니다.
그러나 같음 연산자가있는 사용자 지정 구조체에 대해서는이 경고를 생성 하지 않습니다 . 2.0에서는 사용되었지만 3.0 컴파일러에서는 사용되지 않았습니다. 코드는 여전히 제거되지만 (코드에 도달 할 수 없음을 알고 있음) 경고가 생성되지 않습니다.
using System;
struct MyValue
{
private readonly int value;
public MyValue(int value) { this.value = value; }
public static bool operator ==(MyValue x, MyValue y) {
return x.value == y.value;
}
public static bool operator !=(MyValue x, MyValue y) {
return x.value != y.value;
}
}
class Program
{
static void Main()
{
int i = 1;
MyValue v = new MyValue(1);
if (i == null) { Console.WriteLine("a"); } // warning
if (v == null) { Console.WriteLine("a"); } // no warning
}
}
IL (for Main
)- (부작용을 가질 수 있음)을 제외한 모든MyValue(1)
것이 제거되었습니다.
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 i,
[1] valuetype MyValue v)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: ldloca.s v
L_0004: ldc.i4.1
L_0005: call instance void MyValue::.ctor(int32)
L_000a: ret
}
이것은 기본적으로 :
private static void Main()
{
MyValue v = new MyValue(1);
}
답변
비교가 결코 사실 일 수 없다는 사실이 그것이 불법임을 의미하지는 않습니다. 그럼에도 불구하고 값 유형은 null
.
답변
아니, Int32 x
절대 null
.
int를 null과 비교하는 경우 두 개의 int를 취하는 비교 연산자를 적용 할 수 있습니다.
“값 유형을 null과 비교하는 것이 경고 인 이유는 무엇입니까?” 기사가 도움이 될 것입니다.
답변
값 유형은 null
같을 수 있지만 null
(고려 Nullable<>
) 일 수 없습니다 . 귀하의 경우 int
변수 및 null
암시 적으로 캐스팅 Nullable<Int32>
되고 비교됩니다.
답변
테스트가 거짓이 아니기 때문에 IL을 생성 할 때 특정 테스트가 컴파일러에 의해 최적화되고 있다고 생각합니다.
참고 : nullable Int32가 Int32를 사용하도록 할 수 있습니까? x 대신.
답변
나는 이것이 “==”가 실제로 매개 변수 System.Object.Equals
를 받아들이는 메소드에 대한 호출을 나타내는 구문 설탕이기 때문이라고 생각한다 System.Object
. ECMA 사양에 의한 Null은 물론에서 파생 된 특수 유형입니다 System.Object
.
그것이 경고 만있는 이유입니다.