次のコードについていくつか質問があります。
using System;
namespace ConsoleApplication2
{
public struct Disposable : IDisposable
{
public void Dispose() { }
}
class Program
{
static void Main(string[] args)
{
using (Test()) { }
}
static Disposable Test()
{
return new Disposable();
}
}
}
私の質問は次のとおりです。
- ボックス
Disposable
から返された構造体で動作する using ステートメントは、構造体であるかどうか。Test()
- どうすれば自分で答えを見つけることができますか?
自分自身を見つけようとするために、上記のコードによって生成された IL を調べました。Main(...)
メソッドの IL は次のとおりです。
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] valuetype ConsoleApplication2.Disposable CS$3$0000)
L_0000: call valuetype ConsoleApplication2.Disposable ConsoleApplication2.Program::Test()
L_0005: stloc.0
L_0006: leave.s L_0016
L_0008: ldloca.s CS$3$0000
L_000a: constrained ConsoleApplication2.Disposable
L_0010: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_0015: endfinally
L_0016: ret
.try L_0006 to L_0008 finally handler L_0008 to L_0016
}
そこにある仮想メソッドの呼び出しがボックス化操作を導入すると思われますL_0010
が、実際のbox
命令はここにはありません。
私が尋ねている理由は、しばらく前、おそらく 1 ~ 2 年前に、誰かがコメントした using ステートメントの「最適化」をオンラインで見たからです。オブジェクトの短時間ロックの構文として using ステートメントが使用され、メソッドでロックが取得され、構造体が返され、破棄されるとロックが解放される場合がありました。コードは次のようになります。 :
using (LockTheObject())
{
// use the object
}
コメントは、LockTheObject
メソッドの戻り値の型をIDisposable
実際に使用される構造体に変更することで、ボクシングが回避されたというものでした。
しかし、私はこれが本当なのか、それともまだ本当なのか疑問に思っています。
誰かが私を正しい方向に向けることができますか? ボックスの操作を確認するためにランタイム アセンブリ コードを検査する必要がある場合は、何を探すべきかの例を示してください。私はアセンブリ コードに精通しているので問題ありませんが、何も飛び出していません。私もそれを見たとき。