13

This one has confused me a little... Attempting to dispose of an XmlReader

XmlReader reader = XmlReader.Create(filePath);
reader.Dispose();  

Provides the following error:

'System.Xml.XmlReader.Dispose(bool)' is inaccessible due to its protection level

however the following is fine:

using(XmlReader reader = XmlReader.Create(filePath))
{
}

When I look at the definition in Reflector I can't understand why I can't call Dispose

XmlReader

Implementation of Dispose:

Dispose

Can anyone point out what I'm missing?

Ian
  • 33,605
  • 26
  • 118
  • 198

2 Answers2

19

The problem is that XmlReader uses explicit interface implementation to implement IDisposable. So you can write:

XmlReader reader = XmlReader.Create(filePath);
((IDisposable)reader).Dispose();

However, I'd strongly suggest using a using statement anyway. It should be very rare that you call Dispose explicitly, other than within another Dispose implementation.

EDIT: As noted, this is "fixed" in .NET 4.5, in that it exposes a public parameterless Dispose method as of .NET 4.5 as well as the explicit interface implementation. So presumably you're compiling against .NET 4.0 or earlier (perhaps .NET 2.0 given your tags) but using Reflector against .NET 4.5?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This seems to be 'fixed' in .NET 4. I wonder what the original intention was with the explicit implementation? – leppie Mar 06 '12 at 11:12
  • @leppie: Not sure, but I think it's true of a few classes - this isn't the first time I've seen it. – Jon Skeet Mar 06 '12 at 11:14
  • 1
    `System.Xml` is not exactly know for it's good style ;p IIRC several `new` members etc in .NET 1.x (not sure about newer ones). – leppie Mar 06 '12 at 11:16
  • @JonSkeet: Thanks for the good answer. Yeah, I'm compiling against .NET 2.0 (I'll update my tags) and I imagine much of the confusion came from Reflector not showing the assembly I thought it was... I thought I'd switched to .NET 2.0 but obviously not. – Ian Mar 06 '12 at 11:42
  • Looks to me like this was 'fixed'/changed in .NET 4.5, not .NET 4 as suggested above. It's confusing because the 4.5 assemblies have a 4.0.x version number. – redcalx Feb 23 '15 at 12:16
  • 1
    @locster: It's not that that confused me - it's that you can select .NET 4 as the framework version, at which point it shows that it's available for PCLs. All very odd. Will update the answer though. – Jon Skeet Feb 23 '15 at 12:46
-2
using(XmlReader reader = XmlReader.Create(filePath))
{
   foo(reader);
}

is exactly equivalent to

XmlReader reader = XmlReader.Create(filePath);
try 
{
   code(reader);
} 
finally
{
   if(reader != null)
     ((IDisposable)reader).Dispose();
}

The most likely thing is that you haven't posted all of your code - perhaps someone else is calling Dispose() on your object as well, causing an exception in the second call to Dispose()?

SecurityMatt
  • 6,593
  • 1
  • 22
  • 28
  • 4
    No, it's not exactly equivalent to that. It handles nullity, and it implicitly casts to `IDisposable` if required due to explicit interface implementation - which is the case here. – Jon Skeet Mar 06 '12 at 11:10
  • 1
    Pre-.NET 4.0, XmlReader implements IDisposable explicitly. Your `reader.Dispose()` should be `((IDisposable)reader).Dispose()` – Joe Mar 06 '12 at 11:11
  • 3
    ''The most likely thing is that you haven't posted all of your code'' If you'd tried it, those two lines he posted were enough to show the problem. – weston Mar 06 '12 at 11:21
  • As weston said... The code I posted is exactly that, it's a build error not a runtime error. – Ian Mar 06 '12 at 11:59