문제

스택 오버플로 질문에 참여하고있었습니다 .net의 모든 것이 객체입니까?.

그리고 하나의 포스터 (허용 된 답변에 대한 의견에서)는 값 유형에서 메소드 호출을 수행하면 복싱이 발생했다고 생각하는 것 같습니다. 그는 나를 지적했다 권투 및 개봉 (C# 프로그래밍 안내서) 우리가 설명하는 사용 사례를 정확하게 지정하지 않습니다.

나는 단일 소스를 신뢰하는 사람이 아니므로 질문에 대한 추가 피드백을 받고 싶었습니다. 내 직관은 권투가 없지만 직관이 빨라진다는 것입니다. :디

더 자세히 설명하기 위해 :

내가 사용한 예는 다음과 같습니다.

int x = 5;
string s = x.ToString(); // Boxing??

권투가합니다 ~ 아니다 문제의 구조물이 여기에서 허용 된 답변이 표시된대로 객체에서 상속 된 메소드를 무시하는 경우 발생합니다.

그러나 구조물이 방법을 무시하지 않으면 "제한" 명령은 callvirt 전에 실행됩니다. 문서에 따르면 opcodes. 제한 된 필드, 이로 인해 복싱이 발생합니다:

이 유형이 값 유형이고 thistype가 메소드를 구현하지 않으면 PTR은 CallVirt 메소드 명령어에 대한 '이'포인터로 도입되고 박스형 및 전달됩니다.

도움이 되었습니까?

해결책

코드의 IL은 다음과 같습니다.

L_0001: ldc.i4.5      // get a 5 on the stack
L_0002: stloc.0       // store into x
L_0003: ldloca.s x    // get the address of x on the stack
L_0005: call instance string [mscorlib]System.Int32::ToString()  // ToString
L_000a: stloc.1       // store in s

따라서이 경우의 대답은 아니오입니다.

다른 팁

주인이 지적한 것처럼 답은 대답을 한 경우에 답을 얻었습니다.

그러나 인터페이스 포인터를 통해 메소드를 호출하면됩니다.

코드를 고려하십시오 :

interface IZot
{
    int F();
}

struct Zot : IZot
{
    public int F()
    {
        return 123;
    }
}

그 다음에

Zot z = new Zot();
z.F();

하다 ~ 아니다 복싱 결과 :

.locals init (
    [0] valuetype ConsoleApplication1.Zot z)
L_0000: nop 
L_0001: ldloca.s z
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloca.s z
L_000b: call instance int32 ConsoleApplication1.Zot::F()
L_0010: pop 
L_0011: ret 

그러나 이것은 다음과 같습니다.

IZot z = new Zot();
z.F();

   .locals init (
        [0] class ConsoleApplication1.IZot z,
        [1] valuetype ConsoleApplication1.Zot CS$0$0000)
    L_0000: nop 
    L_0001: ldloca.s CS$0$0000
    L_0003: initobj ConsoleApplication1.Zot
    L_0009: ldloc.1 
    L_000a: box ConsoleApplication1.Zot
    L_000f: stloc.0 
    L_0010: ldloc.0 
    L_0011: callvirt instance int32 ConsoleApplication1.IZot::F()
    L_0016: pop 

@GGF31316

"나는 구조가 방법을 무시하지 않으면 Tostring, Equals 및 gethashcode를 호출하면 복싱이 발생한다고 생각한다."

나는 당신을 위해 Tostring을 확인했습니다. int32는 Tostring을 무시하므로 그렇지 않은 구조물을 만들었습니다. 나는 사용했다 .NET 리플렉터 구조물이 어떻게 든 마술처럼 마술처럼 Tostring ()을 무시하지 않았는지 확인했습니다.

그래서 코드는 다음과 같습니다.

using System;

namespace ConsoleApplication29
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStruct ms = new MyStruct(5);
            string s = ms.ToString();
            Console.WriteLine(s);
        }
    }

    struct MyStruct
    {
        private int m_SomeInt;

        public MyStruct(int someInt)
        {
            m_SomeInt = someInt;
        }

        public int SomeInt
        {
            get
            {
                return m_SomeInt;
            }
        }
    }
}

그리고 MSIL (비아 ildasm) 주요 방법은 다음과 같습니다.

  IL_0000:  ldloca.s   ms
  IL_0002:  ldc.i4.5
  IL_0003:  call       instance void ConsoleApplication29.MyStruct::.ctor(int32)
  IL_0008:  ldloca.s   ms
  IL_000a:  constrained. ConsoleApplication29.MyStruct
  IL_0010:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0015:  stloc.1
  IL_0016:  ldloc.1
  IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001c:  ret

이제 권투 통화가 발생하지 않더라도 확인하면 제한된 + 통화 미덕에 대한 문서, 당신은 권투가 일어난다는 것을 알게 될 것입니다. 우

인용하다:

이 유형이 값 유형이고 thistype가 메소드를 구현하지 않으면 PTR은 CallVirt 메소드 명령어에 대한 '이'포인터로 도입되고 박스형 및 전달됩니다.

구조가 메소드를 무시하지 않으면 Tostring, Equals 및 gethashcode를 호출하면 복싱이 발생한다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top