This really is interesting!.
It is apparent that combination of the use of an existing variable in the using() statement and the reassignment of the original within the block, results in a new reference which is passed to Dispose(), and not the existing _proxy, as per the IL below.
In fact, LinqPad issues a warning to this effect:
Possibly incorrect assignment to local 'variable' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
However this behaviour does not appear to require a cast to as IDisposable, nor does the static seem to have any effect.
Disassembling the following code to IL in LINQPad:
IMyService _proxy = null;
if (_proxy == null)
{
   using (_proxy)
   {
      _proxy = new SomeService();
   }
}
Yields
IL_0001:  ldnull      
IL_0002:  stloc.0     // _proxy
IL_0003:  ldloc.0     // _proxy
IL_0004:  ldnull      
IL_0005:  ceq         
IL_0007:  ldc.i4.0    
IL_0008:  ceq         
IL_000A:  stloc.1     // CS$4$0000
IL_000B:  ldloc.1     // CS$4$0000
IL_000C:  brtrue.s    IL_002D
IL_000E:  nop         
** IL_000F:  ldloc.0     // _proxy
** IL_0010:  stloc.2     // CS$3$0001
IL_0011:  nop         
IL_0012:  newobj      UserQuery+SomeService..ctor
IL_0017:  stloc.0     // _proxy
IL_0018:  nop         
IL_0019:  leave.s     IL_002B
$IL_001B:  ldloc.2     // CS$3$0001
$IL_001C:  ldnull      
$IL_001D:  ceq         
IL_001F:  stloc.1     // CS$4$0000
IL_0020:  ldloc.1     // CS$4$0000
$IL_0021:  brtrue.s    IL_002A
** IL_0023:  ldloc.2     // CS$3$0001
IL_0024:  callvirt    System.IDisposable.Dispose
IL_0029:  nop         
IL_002A:  endfinally  
IL_002B:  nop         
As can be seen (by the **'s), that a new loc 2 is created, and it is this reference which is passed to Dispose(). But prior to this is a check for null ($), which bypasses the Dispose in any event.
Contrast this with the explicit try-finally:
 if (_proxy == null)
 {
    try
    {
       _proxy = new SomeService();
    }
    finally
    {
       _proxy.Dispose();
    }
 }
IL_0001:  ldnull      
IL_0002:  stloc.0     // _proxy
IL_0003:  ldloc.0     // _proxy
IL_0004:  ldnull      
IL_0005:  ceq         
IL_0007:  ldc.i4.0    
IL_0008:  ceq         
IL_000A:  stloc.1     // CS$4$0000
IL_000B:  ldloc.1     // CS$4$0000
IL_000C:  brtrue.s    IL_0025
IL_000E:  nop         
IL_000F:  nop         
IL_0010:  newobj      UserQuery+SomeService..ctor
IL_0015:  stloc.0     // _proxy
IL_0016:  nop         
IL_0017:  leave.s     IL_0023
IL_0019:  nop         
** IL_001A:  ldloc.0     // _proxy
IL_001B:  callvirt    System.IDisposable.Dispose
IL_0020:  nop         
IL_0021:  nop         
IL_0022:  endfinally  
IL_0023:  nop      
Where it can be clearly seen that it is the "original" _proxy which is Disposed, without the extra null check done in the using(), confirming the docs.
Needless to say this code is evil:
- _proxywill never be- Disposed, viz the- usingis redundant.
- It relies on passing null to usingnot failing.
- Because _proxyis defined prior to theusing, it can be reassigned within the block, unlike variables declared IN the using statement - e.g.using (var _proxy = ...)would beread-only, and attempting to mutate such a variable would result in a compile time error anyway.
- The merits of static singleton channels aside, the lazy initialization of _proxyis also not thread-safe (e.g. no double-check lock), and could be simplified with aprivate static readonly Lazy<IMyService>(() => ...)and a simple getter.