Reputation: 13
I have an abstract class:
public abstract class Node
{
protected readonly List<Node> Nodes = new List<Node>();
public Node[] ChildNodes => Nodes.ToArray();
...
}
And derived from him:
public sealed class NodeArray<T> : Node where T: Node
{
private readonly List<T> _array = new List<T>();
private new List<Node> Nodes => _array.Cast<Node>().ToList();
public new Node[] ChildNodes => _array.Cast<Node>().ToArray();
...
}
Node.Nodes list may contain NodeArray<Smth> through. But, when I'm trying to recursively enumerate nodes, and I'm getting one of type NodeArray, it returns empty ChildNodes value (of base class I guess). And when I debugged following code, Intellisense shows two identical properties with the same name and same type!
Loop code:
protected void LoadNode(Node node, XmlNode xmlNode)
{
foreach (XmlNode childNode in xmlNode.ChildNodes)
{
if (childNode.HasChildNodes)
{
var child = node.ChildNodes.First(p => p.Name == childNode.Name); // <----- Stuck here
if(child == null)
throw new Exception("Unknown child " + childNode.Name + " in Node " + node.Name);
LoadNode(child, childNode);
}
else
{
node[childNode.Name] = childNode.Value;
}
}
node.Load();
}
Hope you help! Sorry for bed English :)
Upvotes: 0
Views: 50
Reputation: 54877
Your issue might be that you're using member hiding (with the new
keyword) rather than overriding. With member hiding, the base class and the derived class contain separate definitions of the property, despite having the same name. Thus, if you create a NodeArray<T>
instance, populate its _array
collection, and then pass it as a Node
reference, then ChildNodes
property would still be returning the empty collection of the Node.Nodes
base property, rather than the NodeArray<T>._array
field like you'd expect.
To resolve this issue, switch to using virtual and overridden members, as shown below:
public abstract class Node
{
protected virtual List<Node> Nodes { get; } = new List<Node>();
public virtual Node[] ChildNodes => Nodes.ToArray();
...
}
public sealed class NodeArray<T> : Node where T: Node
{
private readonly List<T> _array = new List<T>();
protected override List<Node> Nodes => _array.Cast<Node>().ToList();
public override Node[] ChildNodes => _array.Cast<Node>().ToArray();
...
}
Upvotes: 1