[Mono-bugs] [Bug 571010] New: using(){} with structs shouldn't box to invoke explicitly implemented IDisposable.Dispose method

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Fri Jan 15 12:06:11 EST 2010


http://bugzilla.novell.com/show_bug.cgi?id=571010

http://bugzilla.novell.com/show_bug.cgi?id=571010#c0


           Summary: using(){} with structs shouldn't box to invoke
                    explicitly implemented IDisposable.Dispose method
    Classification: Mono
           Product: Mono: Compilers
           Version: SVN
          Platform: x86-64
        OS/Version: openSUSE 11.2
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: C#
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: jpryor at novell.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---
           Blocker: ---


>From §15.13 (page 248) in:

  http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

the statement:

  using (ResourceType resource = expression) embedded-statement

should expand to

  {
    ResourceType resource = expression;
    try {
      embedded-statement
    }
    finally {
      ((System.IDisposable)resource).Dispose();
    }
  }

when ResourceType is a value type (struct).  *Additionally*:

  "casting resource to System.IDisposable shall not cause boxing 
  to occur."

Thus, consider the following program:

    using System;

    struct Foo : IDisposable {
        void IDisposable.Dispose(){}
        public void Dispose() {}
    }

    class Test {
        public static void Main ()
        {
            using (new Foo()) {
            }
        }
    }

Compile:

  $ gmcs us.cs

Disassemble, and check out the IL for Test.Main():

        // Method begins at RVA 0x20fc
        .entrypoint
        // Code size 26 (0x1a)
        .maxstack 2
        .locals init (
                valuetype Foo   V_0)
        IL_0000:  ldloca.s 0
        IL_0002:  initobj Foo
        .try { // 0
          IL_0008:  leave IL_0019

        } // end .try 0
        finally  { // 0
          IL_000d:  ldloc.0 
          IL_000e:  box Foo
          IL_0013:  callvirt instance void class
[mscorlib]System.IDisposable::Dispose()
          IL_0018:  endfinally 
        } // end handler 0
        IL_0019:  ret 

Notice that gmcs IS boxing here.  gmcs isn't following ECMA.

Compare to what .NET CSC does; same source, different IL:

        // Method begins at RVA 0x2058
        .entrypoint
        // Code size 30 (0x1e)
        .maxstack 1
        .locals init (
                valuetype Foo   V_0)
        IL_0000:  nop 
        IL_0001:  ldloca.s 0
        IL_0003:  initobj Foo
        .try { // 0
          IL_0009:  nop 
          IL_000a:  nop 
          IL_000b:  leave.s IL_001c

        } // end .try 0
        finally  { // 0
          IL_000d:  ldloca.s 0
          IL_000f:  constrained. Foo
          IL_0015:  callvirt instance void class
[mscorlib]System.IDisposable::Dispose()
          IL_001a:  nop 
          IL_001b:  endfinally 
        } // end handler 0
        IL_001c:  nop 
        IL_001d:  ret 

Notice that CSC uses a 'constrained. Foo' instead of 'box Foo' to avoid boxing.

gmcs shouldn do likewise to avoid boxing the resource.

(Note that if you don't explicitly implement IDisposable.Dispose(), gmcs will
properly avoid boxing the resource, so this is only an issue for explicitly
implemented IDisposable.Dispose() methods.)

-- 
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list