programing

Nullable의 복싱/언복싱 동작은 어떻게 가능합니까?

powerit 2023. 5. 28. 21:05
반응형

Nullable의 복싱/언복싱 동작은 어떻게 가능합니까?

오늘 아침에 갑자기 머리가 긁히는 일이 생겼습니다.

모든 유형의 변수Nullable<T>에 할당할 수 있습니다.null예를 들어:

int? i = null;

처음에 저는 어떻게든 암시적 변환을 정의하지 않고 어떻게 이것이 가능한지 볼 수 없었습니다.object로.Nullable<T>:

public static implicit operator Nullable<T>(object box);

그러나 위 연산자는 분명히 존재하지 않습니다. 마치 존재했던 것처럼 다음 연산자도 합법적이어야 합니다. 적어도 컴파일 시간에는 그렇지 않습니다.

int? i = new object();

그때 깨달았어요 아마도Nullable<T>type은 다음과 같이 인스턴스화할 수 없는 임의의 참조 유형으로 암시적 변환을 정의할 수 있습니다.

public abstract class DummyBox
{
    private DummyBox()
    { }
}

public struct Nullable<T> where T : struct
{
    public static implicit operator Nullable<T>(DummyBox box)
    {
        if (box == null)
        {
            return new Nullable<T>();
        }

        // This should never be possible, as a DummyBox cannot be instantiated.
        throw new InvalidCastException();
    }
}

하지만, 이것은 다음에 나에게 무슨 일이 일어났는지 설명하지 못합니다: 만약에.HasValue재산은false어떤 경우에도Nullable<T>값을 입력하면 해당 값이 다음과 같이 상자에 표시됩니다.null:

int? i = new int?();
object x = i; // Now x is null.

게다가, 만약에HasValue이라true그러면 값이 상자로 표시됩니다.T가 아니라T?:

int? i = 5;
object x = i; // Now x is a boxed int, NOT a boxed Nullable<int>.

하지만 이것은 다음과 같은 경우의 사용자 정의 암묵적 변환이 있다는 것을 의미하는 것으로 보입니다.Nullable<T>로.object:

public static implicit operator object(Nullable<T> value);

이것은 분명히 사실이 아닙니다.object는 모든 유형에 대한 기본 클래스이며, 기본 유형에서 사용자 정의 암시적 변환은 불법입니다.

는 것 같습니다.object x = i;박스에 넣어주세요.i다른 가치 유형과 마찬가지로, 그래서.x.GetType()와 동일한 결과를 산출할 것입니다.typeof(int?)(던지기 보다는)NullReferenceException).

그래서 저는 주변을 좀 둘러보았고, 물론, 이 행동은 특정한 것으로 밝혀졌습니다.Nullable<T>C# 및 VB.NET 사양 모두에서 특별히 정의되며 사용자 정의에서는 재현할 수 없는 유형struct(C#) 또는Structure(VB.NET).

제가 아직도 혼란스러운 이유가 여기 있습니다.

이러한 특정 복싱 및 언복싱 동작은 손으로 구현하는 것이 불가능한 것으로 보입니다.C#과 VB.NET 둘 다 특별한 치료를 제공하기 때문에 작동합니다.Nullable<T>유형.

  1. 이론적으로 다른 CLI 기반 언어가 존재할 수 있지 않습니까?Nullable<T>이런 특별한 대우를 받지 않았습니까?그리고 그것은.Nullable<T>따라서 유형은 다른 언어에서 다른 행동을 나타냅니까?

  2. C# 및 VB.NET은 어떻게 이 동작을 수행합니까?CLR에서 지원합니까? (즉, CLR은 C# 및 VB.NET 자체가 금지하더라도 유형이 박스 방식을 "오버라이드"할 수 있습니까?)

  3. (C# 또는 VB.NET에서) a를 상자에 넣는 것이 가능합니까?Nullable<T>~하듯이object?

두 가지 일이 진행되고 있습니다.

컴파일러는 "null"을 null 참조가 아닌 null 값으로 처리합니다.변환해야 하는 유형에 대한 null 값입니다.의 경우Nullable<T> 입니다.HasValue밭/밭그래서 만약 당신이 유형의 변수를 가지고 있다면.int?그 변 값 다 음 같 가 을 있 꽤 니 습 다 이 성 능 과 수 의 이 다 ▁for ▁it ▁to ▁possible ▁quite 니 ▁variable s 있 ▁of 습 ▁be ' ▁the ▁value 꽤 ▁thatnull당신은 단지 무엇에 대한 당신의 이해를 바꿀 필요가 있습니다.null약간의 의미가 있습니다.

복싱 무효형은 CLR 자체에 의해 특별 대우를 받습니다.이는 두 번째 예와 관련이 있습니다.

    int? i = new int?();
    object x = i;

컴파일러는 null 가능한 형식 값을 null 불가능한 형식 값과 다르게 상자에 넣습니다.null이이 아닌 을 상자에 넣는 null이 null이 아닌 을 사용할 수 없습니다. 따라서int?값이 5인 경우와 동일한 방식으로 상자에 들어갑니다.int값 5 - "가용성"이 손실됩니다.그러나 null 가능한 유형의 null 값은 개체를 전혀 생성하지 않고 null 참조로만 상자에 표시됩니다.

이는 CLR v2 사이클 후반에 커뮤니티의 요청에 따라 도입되었습니다.

이는 "상자에 들어 있는 nullable-value-type 값"과 같은 것이 없음을 의미합니다.

당이옳습다니신다니.Nullable<T>와 C. VB 및 C# 모 에 서 러 로 부 받 니 습 다 를 처 터 리 특 한 수 일따라서:

  1. 한 대소문자를 사용해야 . 언컴파케필요다이니합가스네특수.Nullable<T>.
  2. 는 컴일러는다사리팩다니합터용을의 을 .Nullable<T>연산자는 단지 통사적인 설탕일 뿐입니다.
  3. 아는 바 없는데요.

저는 저 자신에게 같은 질문을 하고 있었고 또한 저는 암시적인 연산자가 있을 것이라고 기대했습니다.Nullable<T>.net Null 가능 소스 코드에서 IL 코드가 무엇인지 살펴봤습니다.int? a = null;현장에서 무슨 일이 일어나고 있는지 이해하는 것:

c# 코드:

int? a = null;
int? a2 = new int?();
object a3 = null;
int? b = 5;
int? b2 = new int?(5);

IL 코드(LINQPad 5로 생성):

IL_0000:  nop         
IL_0001:  ldloca.s    00 // a
IL_0003:  initobj     System.Nullable<System.Int32>
IL_0009:  ldloca.s    01 // a2
IL_000B:  initobj     System.Nullable<System.Int32>
IL_0011:  ldnull      
IL_0012:  stloc.2     // a3
IL_0013:  ldloca.s    03 // b
IL_0015:  ldc.i4.5    
IL_0016:  call        System.Nullable<System.Int32>..ctor
IL_001B:  ldloca.s    04 // b2
IL_001D:  ldc.i4.5    
IL_001E:  call        System.Nullable<System.Int32>..ctor
IL_0023:  ret   

컴파일러가 변경되는 것을 볼 수 있습니다.int? a = null와 비슷한 정도로int? a = new int?()은 상는당다른히와 상당히 .object a3 = null따라서 Nullables에는 특별한 컴파일러 처리가 있습니다.

언급URL : https://stackoverflow.com/questions/3775582/how-is-the-boxing-unboxing-behavior-of-nullablet-possible

반응형