C# Multi level HTML TagBuilder object - Design pattern Review needed I find the TagBuilder written in C# little poor without the ability to "host" inside it sub tags (as objects not as strings).

So I wrote a simple class that inherits TagBuilder and allow to save sub tags.
I can navigate inside it and add things to it while I move across the application.
And when I call the Top Tag Object .ToString, it will render the entire html

public class MultiLevelHtmlTag : TagBuilder
{
    public MultiLevelHtmlTag(string tagName) : base(tagName) { }

    public List&lt;MultiLevelHtmlTag&gt; InnerTags = new List&lt;MultiLevelHtmlTag&gt;();



    public override string ToString()
    {
        if (InnerTags.Count &gt; 0)
        {
            foreach (MultiLevelHtmlTag tag in InnerTags)
            {
                this.InnerHtml += tag.ToString();
            }
        }
        return base.ToString();
    }
}


this is how I use it:

MultiLevelHtmlTag top = new MultiLevelHtmlTag("div");
top.InnerTags.Add(new MultiLevelHtmlTag("span"));
log.Debug(top.ToString());


output:

&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;


What do you think about it?
is that a goot pattern?
I would make sure the list is not exposed publicly - the caller can then do whatever they want with that list, even assign null to it.  So I've refactored it a little bit and implemented Add() (you may also want to implement Remove(), etc.):

/// &lt;summary&gt;
/// Simple class that inherits TagBuilder and allow to save sub tags.
/// &lt;/summary&gt;
public class MultiLevelHtmlTag : TagBuilder
{
    /// &lt;summary&gt;
    /// List of inner tags.
    /// &lt;/summary&gt;
    private readonly IList&lt;MultiLevelHtmlTag&gt; innerTags = new List&lt;MultiLevelHtmlTag&gt;();

    /// &lt;summary&gt;
    /// Initializes a new instance of the &lt;see cref="MultiLevelHtmlTag"/&gt; class.
    /// &lt;/summary&gt;
    /// &lt;param name="tagName"&gt;The name of the tag.&lt;/param&gt;
    public MultiLevelHtmlTag(string tagName) : base(tagName)
    {
    }

    /// &lt;summary&gt;
    /// Gets the inner tag list.
    /// &lt;/summary&gt;
    /// &lt;value&gt;The inner tag list.&lt;/value&gt;
    public IEnumerable&lt;MultiLevelHtmlTag&gt; InnerTags
    {
        get
        {
            return new ReadOnlyCollection&lt;MultiLevelHtmlTag&gt;(this.innerTags);
        }
    }

    /// &lt;summary&gt;
    /// Adds the specified tag to the inner tag list.
    /// &lt;/summary&gt;
    /// &lt;param name="tag"&gt;The tag to add.&lt;/param&gt;
    public void Add(MultiLevelHtmlTag tag)
    {
        if (tag == null)
        {
            throw new ArgumentNullException("tag");
        }

        this.innerTags.Add(tag);
    }

    /// &lt;summary&gt;
    /// Returns a &lt;see cref="System.String"/&gt; that represents this instance.
    /// &lt;/summary&gt;
    /// &lt;returns&gt;
    /// A &lt;see cref="System.String"/&gt; that represents this instance.
    /// &lt;/returns&gt;
    public override string ToString()
    {
        var sb = new StringBuilder();

        foreach (var tag in this.innerTags)
        {
            sb.Append(tag.ToString());
        }

        this.InnerHtml = sb.ToString();
        return base.ToString();
    }
}