programing

"x is null"과 "x == null"의 차이점은 무엇입니까?

iphone6s 2023. 5. 12. 21:43
반응형

"x is null"과 "x == null"의 차이점은 무엇입니까?

C# 7에서 우리는

if (x is null) return;

대신에

if (x == null) return;

기존 방식보다 새로운 방식(이전의 예)을 사용하면 어떤 이점이 있습니까?

의미론이 다릅니까?

그것은 단지 취향의 문제입니까?만약 그렇지 않다면, 저는 언제 하나를 다른 하나보다 더 사용해야 합니까?

참조:C# 7.0의 새로운 기능

업데이트: 로슬린 컴파일러는 오버로드된 동등 연산자가 없을 때 두 연산자의 동작을 동일하게 하도록 업데이트되었습니다.현재 컴파일러 결과에서 코드를 확인하십시오.M1그리고.M2코드에서) 오버로드된 동등성 비교기가 없을 때 발생하는 상황을 보여줍니다.이제 둘 다 더 나은 성능을 갖게 되었습니다.==행동.오버로드된 동등성 비교기가 있는 경우 코드는 여전히 다릅니다.

Roslin 컴파일러의 이전 버전은 아래 분석을 참조하십시오.


위해서null우리가 C#6에 익숙한 것과 차이가 없습니다. 하지만 당신이 바뀌면 상황이 흥미로워집니다.null다른 상수로

예를 들어 다음과 같습니다.

Test(1);

public void Test(object o)
{
    if (o is 1) Console.WriteLine("a");
    else Console.WriteLine("b");
}

시험 결과.a그것을 와 비교하면o == (object)1당신이 정상적으로 썼을 것이라면, 그것은 많은 차이를 만듭니다. is비교의 다른 쪽에 있는 유형을 고려합니다.와, 멋진데!

제 생각엔== null대.is null상수 패턴은 단지 매우 친숙한 '우연한' 것일 뿐이며, 여기서 구문입니다.is측정 시스템과 동등한 측정 시스템은 동일한 결과를 산출합니다.


svick이 말한 처럼, 어디로 전화를 걸어요.

에 대한 ILis:

IL_0000: ldarg.1              // Load argument 1 onto the stack
IL_0001: ldnull               // Push a null reference on the stack
IL_0002: call bool [mscorlib]System.Object::Equals(object, object) // Call method indicated on the stack with arguments
IL_0007: ret                  // Return from method, possibly with a value

에 대한 IL==:

IL_0000: ldarg.1              // Load argument 1 onto the stack
IL_0001: ldnull               // Push a null reference on the stack
IL_0002: ceq                  // Push 1 (of type int32) if value1 equals value2, else push 0
IL_0004: ret                  // Return from method, possibly with a value

우리가 얘기하고 있는 이상.null인스턴스에만 차이가 있기 때문에 차이가 없습니다.등호 연산자를 오버로드한 경우 변경될 수 있습니다.

오버로드된 동일 연산자

당신이 비교할 때 두 비교 사이에는 사실 의미론의 차이가 있습니다.null오버로드된 유형으로==교환입니다. foo is null직접 참조 비교를 사용하여 결과를 결정하는 반면,foo == null물론 과부하가 걸린 것을 실행할 것입니다.==연산자(존재하는 경우).

이 예에서는 오버로드된 "버그"를 도입했습니다.==연산자, 두 번째 인수가 다음과 같은 경우 항상 예외를 던지게 합니다.null:

void Main()
{
    Foo foo = null;

    if (foo is null) Console.WriteLine("foo is null"); // This condition is met
    if (foo == null) Console.WriteLine("foo == null"); // This will throw an exception
}

public class Foo
{
    public static bool operator ==(Foo foo1, Foo foo2)
    {
        if (object.Equals(foo2, null)) throw new Exception("oops");
        return object.Equals(foo1, foo2);
    }

    // ...
}

다에대한 IL 드코의 .foo is null를 사용합니다.ceq직접 참조 비교를 수행하기 위한 지침:

IL_0003:  ldloc.0     // foo
IL_0004:  ldnull      
IL_0005:  ceq

다에대한 IL 드코의 .foo == null오버로드된 연산자에 대한 호출을 사용합니다.

IL_0016:  ldloc.0     // foo
IL_0017:  ldnull      
IL_0018:  call        UserQuery+Foo.op_Equality

에 그서다점만당약이신을 한다면,==사용자 코드를 실행할 위험이 있습니다(예상치 못한 동작이나 성능 문제가 발생할 수 있음).

제네릭 제한

is null형식으로 합니다. 를 참조합니다.는 이것을합니다. 즉, ., 사할수없니습용파는일것을▁를 사용할 수 .is null방법을 에는 일반적인 방법.is null제네릭 형식이 참조 형식으로 제한되지 않는 한.

bool IsNull<T>(T item) => item is null;                  // Compile error: CS0403
bool IsNull<T>(T item) => item == null;                  // Works
bool IsNull<T>(T item) where T : class => item is null;  // Works

이것을 지적해주신 데이비드 아우구스토 빌라에게 감사드립니다.

이 아닌 할. null과 null은 null과 비교됩니다.을 할 때==는 "을 할 때 Warning을 합니다.is컴파일러가 오류를 발생시킵니다.대해 +1 for 99% 경우의가, 당신컴러게당에신일런그파본인기적다니합원에실를기은치리수소대해▁+1▁most:1▁to,▁compiler▁at▁+다▁for니▁for%합원▁the▁such▁shout%▁want▁99▁you▁99.is null.

여기에 이미지 설명 입력

여기에 이미지 설명 입력

P.S. NetCore 3.1이 설치된 https://dotnetfiddle.net/ 에서 테스트됨

언급URL : https://stackoverflow.com/questions/40676426/what-is-the-difference-between-x-is-null-and-x-null

반응형