25

私はスタック オーバーフローの質問に参加していました。Is everything in .NET an object? .

そして、1人のポスター(受け入れられた回答のコメント)は、値の型でメソッド呼び出しを実行するとボクシングが発生すると考えているようです。彼はBoxing and Unboxing (C# Programming Guide)を教えてくれましたが、これは私たちが説明しているユース ケースを正確に指定していません。

私は単一の情報源を信頼する人ではないので、質問についてさらにフィードバックを得たかっただけです. 私の直感では、ボクシングはありませんが、私の直感は最悪です。:D

さらに詳しく説明するには:

私が使用した例は次のとおりです。

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

ここで受け入れられた回答が示すように、問題の構造体がオブジェクトから継承されたメソッドをオーバーライドする場合、ボクシングは発生しません。

ただし、構造体がメソッドをオーバーライドしない場合は、callvirt の前に「constrain」 CILコマンドが実行されます。ドキュメントOpCodes.Constrained Fieldによると、これによりボクシングが発生します。

thisType が値型であり、thisType がメソッドを実装していない場合、ptr は逆参照され、ボックス化され、'this' ポインターとして callvirt メソッド命令に渡されます。

4

4 に答える 4

18

コードの 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

したがって、この場合の答えはノーです。

于 2009-01-12T18:14:58.427 に答える
7

@ gf31316

「構造がメソッドをオーバーライドしない場合、ToString、Equals、および Gethashcode を呼び出すと、ボックス化が発生すると思います。」

ToString を確認しました。Int32 は ToString をオーバーライドするので、オーバーライドしない構造体を作成しました。.NET Reflectorを使用して、構造体が魔法のように 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;
            }
        }
    }
}

Main メソッドの 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

ここで、ボクシング コールが行われていないにもかかわらず、制約付き + 呼び出し virt に関するドキュメントを確認すると、ボクシングが行われることが示されていることがわかります。oOo

見積もり:

thisType が値型であり、thisType がメソッドを実装していない場合、ptr は逆参照され、ボックス化され、'this' ポインターとして callvirt メソッド命令に渡されます。

于 2009-01-13T11:30:05.700 に答える