Using (IDisposable obj = new ...) in C # to write blocks of code in a stream (e.g. XML)

I started using classes that implement IDisposable to write blocks in threads using the using statement. This is useful to maintain proper nesting and to avoid missing or improperly placed start / end parts.

In principle, the constructor writes the beginning of the block (for example, opens the XML tag), Dispose () the end (for example, the closing XML tag). The following is an example of a UsableXmlElement (it is for large XML, so LINQ to XML or XmlDocument has no parameters in memory).

However, these IDisposable do not implement the complex template recommended by Microsoft, with Destructor / Finalizer, a separate Dispose (bool) method, and GC.SuppressFinalize (). Dispose just writes the final element and what it is.

Is there any downside to this, or is this a good way to maintain proper nesting of elements?

class UsableXmlElement : IDisposable { private XmlWriter _xwriter; public UsableXmlElement(string name, XmlWriter xmlWriter) { _xwriter = xmlWriter; _xwriter.WriteStartElement(name); } public void WriteAttribute<T>(string name, T value) { _xwriter.WriteStartAttribute(name); _xwriter.WriteValue(value); _xwriter.WriteEndAttribute(); } public void WriteValue<T>(T value) { _xwriter.WriteValue(value); } public void Dispose() { _xwriter.WriteEndElement(); } } 

Usage looks like this:

 var xWriter = new XmlWriter(...) using(var rootElement = new UsableXmlElement("RootElement", xWriter) { rootElement.WriteAttribute("DocVersion", 123) using(var innerElement = new UsableXmlElement("InnerElement", xwriter) { // write anything inside Inner element } } 

Result:

 <RootElement DocVersion="123"> <InnerElement> <!-- anything --> </InnerElement> </RootElement> 
+7
source share
3 answers

The main drawback that I see (in addition to the non-standard use of the using expression, which may violate the "principle of least surprise"), is that it will try to re-write all nested end tags in case of an exception by XmlWriter .

In theory, at least you might have an exception thrown when writing an internal end tag, followed by a successful write of the outer end tags in the finally blocks generated by using. This will lead to an invalid result.

+3
source

Is there any downside to this,

Not. Destructors (finalizers) should be avoided in any case, even a class with resources can usually do (better) without.

or is it a good way to maintain proper nesting of elements?

Yes. You can use System.Web.Mvc.Html.MvcForm as a reference.

these IDisposable do not implement the complex pattern recommended by Microsoft

This "complete" model is correct, but dated. It describes the situation only for a β€œbare” unmanaged resource. Fortunately, official links to working with managed resources are not provided.

+2
source

The sophisticated template used by microsoft is created to ensure that unmanaged resources are freed, even if you do not call Dispose() .

You do not use unmanaged resources in your classes. You simply use the C # using keyword to make your code more readable and maintainable. I think a good approach, and I also used it in the past.

I think it’s even pointless to use the finalizer construct, since you need to be sure that the end tag will be written in the correct position. You never know when the finalizer is called, so you cannot be sure when the end of the tag will be written if you forgot to remove your element. Your Xml document will still be corrupted whether the end tag is not written at all or in the wrong position.

In the worst case, when the finalizer calls Dispose (), the XmlWriter may already be removed and you will get an exception. So the finalizer is better.

+1
source

All Articles