Recursively find all objects of type System.Web.UI.Pair in an object array I have an object array that contains various types of objects (primitives, strings, other object arrays) at arbitrary levels of nesting.  I need to pull all objects of type System.Web.UI.Pair from this array and am having a heck of a time writing the method.  This is especially difficult because the Pair class itself can contain other Pairs or enumerable of Pairs. 

A picture is worth a thousand words:



(Original URL: http://postimage.org/image/i7fuad3b9/)

Here's the method I came up with, but it feels inelegant and incomplete.  Any improvements, especially ones that can leverage LINQ are welcome.

   public static IEnumerable&lt;Pair&gt; Flatten(this object root, List&lt;Pair&gt; list)
    {
        if (root == null)
        {
            return list;
        }
        if (root is Pair)
        {
            var pair = root as Pair;
            list.Add(pair);
            if (pair.First is IEnumerable)
            {
                Flatten((root as Pair).First, list);
            }
            else if (pair.First is Pair)
            {
                list.Add(pair.First as Pair);
            }
            if (pair.Second is IEnumerable)
            {
                Flatten((root as Pair).Second, list);
            }
            else if (pair.Second is Pair)
            {
                list.Add(pair.Second as Pair);
            }
        }
        if (root.GetType().IsArray || root is IEnumerable)
        {
            foreach (object o in (IEnumerable) root)
            {
                Flatten(o, list);
            }
        }
        return list;
    }
You might consider making this an extension method on Pair instead of object.  You could simplify it to this:

public static IEnumerable&lt;Pair&gt; Flatten(this Pair p, List&lt;Pair&gt; toBuild = null)
{
   if (toBuild == null)
      toBuild = new List&lt;Pair&gt;();

   if (p.First is Pair)
   {
      (p.First as Pair).Flatten(toBuild);
   }
   else if (p.First is IEnumerable)
   {
      foreach (object o in (p.First as IEnumerable).OfType&lt;object&gt;().Where(ob =&gt; ob is Pair))
      {
         (o as Pair).Flatten(toBuild);
      }
   }

   //repeat for p.Second

  toBuild.Add(p);
  return toBuild;
}


You can use it like this:

var result = myPair.Flatten();


Or on an IEnumerable&lt;Pair&gt;:

var result = myList.SelectMany(p =&gt; p.Flatten());


Or on a regular IEnumerable:

var result = myList.OfType&lt;object&gt;().Where(o =&gt; o is Pair)
  .SelectMany(p =&gt; (p as Pair).Flatten());