I have been reluctant to offer the code example attached, feeling that I don't have a strong sense, yet, of the "norms" of StackOverFlow in terms of posting code that may be "speculative," and, feeling that this particular frolic is some form of "mutant species" escaped from the laboratory on "The Island of Dr. Moreau" :) And, I do think the answer by Eric Lippert above is right-on. 
So please take what follows with "a grain of salt" as just an experiment in "probing" .NET inheritance (uses FrameWork 3.5 facilities). My goal in writing this (a few months ago) was to experiment with an Abstract Class foundation for Node structure that implemented an internal List<> of "itself," then implement strongly-typed classes that inherited from the Abstract class ... and, on that foundation, build a generalized Tree data structure.
In fact I was surprised when I tested this, that it worked ! :) 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// experimental code : tested to a limited extent
// use only for educational purposes
namespace complexTree
{
    // foundation abstract class template
    public abstract class idioNode
    {
        // a collection of "itself" !
        public List<idioNode> Nodes { private set; get; }
        public idioNode Parent { get; set; }
        public idioNode()
        {
            Nodes = new List<idioNode>();
        }
        public void Add(idioNode theNode)
        {
            Nodes.Add(theNode);
            theNode.Parent = this;
        }
    }
    // strongly typed Node of type String
    public class idioString : idioNode
    {
        public string Value { get; set; }
        public idioString(string strValue)
        {
            Value = strValue;
        }
    }
    // strongly typed Node of type Int
    public class idioInt : idioNode
    {
        public int Value { get; set; }
        public idioInt(int intValue)
        {
            Value = intValue;
        }
    }
    // strongly type Node of a complex type
    // note : this is just a "made-up" test case
    // designed to "stress" this experiment
    // it certainly doesn't model any "real world"
    // use case
    public class idioComplex : idioNode
    {
        public Dictionary<idioString, idioInt> Value { get; set; }
        public idioComplex(idioInt theInt, idioString theString)
        {
            Value = new Dictionary<idioString, idioInt>();
            Value.Add(theString, theInt);
        }
        public void Add(idioInt theInt, idioString theString)
        {
            Value.Add(theString, theInt);
            theInt.Parent = this;
            theString.Parent = this;
        }
    }
    // special case the Tree's root nodes
    // no particular reason for doing this
    public class idioTreeRootNodes : List<idioNode>
    {
        public new void Add(idioNode theNode)
        {
            base.Add(theNode);
            theNode.Parent = null;
        }
    }
    // the Tree object
    public class idioTree
    {
        public idioTreeRootNodes Nodes { get; set; }
        public idioTree()
        {
            Nodes = new idioTreeRootNodes();
        }
    }
}
So, to the test : (call this code from some EventHandler on a WinForm) :
    // make a new idioTree
    idioTree testIdioTree = new idioTree();
    // make a new idioNode of type String
    idioString testIdioString = new idioString("a string");
    // add the Node to the Tree
    testIdioTree.Nodes.Add(testIdioString);
    // make a new idioNode of type Int
    idioInt testIdioInt = new idioInt(99);
    // add to Tree
    testIdioTree.Nodes.Add(testIdioInt);
    // make another idioNode of type String
    idioString testIdioString2 = new idioString("another string");
    // add the new Node to the child Node collection of the Int type Node
    testIdioInt.Nodes.Add(testIdioString2);
    // validate inheritance can be verified at run-time
    if (testIdioInt.Nodes[0] is idioString) MessageBox.Show("it's a string, idiot");
    if (!(testIdioInt.Nodes[0] is idioInt)) MessageBox.Show("it's not an int, idiot");
    // make a new "complex" idioNode
    // creating a Key<>Value pair of the required types of idioNodes
    idioComplex complexIdio = new idioComplex(new idioInt(88), new idioString("weirder"));
    // add a child Node to the complex idioNode
    complexIdio.Add(new idioInt(77), new idioString("too weird"));
    // make another idioNode of type Int
    idioInt idioInt2 = new idioInt(33);
    // add the complex idioNode to the child Node collection of the new Int type idioNode
    idioInt2.Nodes.Add(complexIdio);
    // add the new Int type Node to the Tree
    testIdioTree.Nodes.Add(idioInt2);
    // validate you can verify the type of idioComplex at run-time
    MessageBox.Show(" tree/2/0 is complex = " + (testIdioTree.Nodes[2].Nodes[0] is idioComplex).ToString());
If the "smell" of this code is as bad as the fruit that here in Thailand we call the "durian" : well, so be it :) An obvious possible "weirdness" in this experiment is that you could have references to the same Node in more than one place in the tree at the same time.