[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.

그것이 경고 만있는 이유입니다.