我再次。爲此事道歉。C#泛型 - 以這種方式處理類型參數時爲什麼需要顯式強制轉換?
從我previous question(我想我沒能充分展示我混亂的根源),這裏是實際功能我寫繼:
/// <summary>
/// A b-tree node.
/// </summary>
public class BTreeNode
{
/// <summary>
/// Create a new b-tree node.
/// </summary>
public BTreeNode()
{
}
/// <summary>
/// The node name.
/// </summary>
public string Name
{
get;
set;
}
/// <summary>
/// The left-hand child node.
/// </summary>
public BTreeNode Left
{
get;
set;
}
/// <summary>
/// The right-hand child node.
/// </summary>
public BTreeNode Right
{
get;
set;
}
}
/// <summary>
/// Perform a breadth-first traversal of a b-tree.
/// </summary>
/// <param name="rootNode">
/// The b-tree's root node.
/// </param>
/// <param name="forEachNode">
/// An action delegate to be called once for each node as it is traversed.
/// Also includes the node depth (0-based).
/// </param>
public static void TraverseBreadthFirst<TNode>(this TNode rootNode, Action<TNode, int> forEachNode)
where TNode : BTreeNode
{
if (rootNode == null)
throw new ArgumentNullException("rootNode");
if (forEachNode == null)
throw new ArgumentNullException("forEachNode");
Queue<Tuple<TNode, int>> nodeQueue = new Queue<Tuple<TNode, int>>(3); // Pretty sure there are never more than 3 nodes in the queue.
nodeQueue.Enqueue(new Tuple<TNode, int>(rootNode, 0));
while (nodeQueue.Count > 0)
{
Tuple<TNode, int> parentNodeWithDepth = nodeQueue.Dequeue();
TNode parentNode = parentNodeWithDepth.Item1;
int nodeDepth = parentNodeWithDepth.Item2;
forEachNode(parentNode, nodeDepth);
nodeDepth++;
if (parentNode.Left != null)
nodeQueue.Enqueue(new Tuple<TNode, int>((TNode)parentNode.Left, nodeDepth));
if (parentNode.Right != null)
nodeQueue.Enqueue(new Tuple<TNode, int>((TNode)parentNode.Right, nodeDepth));
}
}
我不知道我爲什麼明確的投到這裏需要TNODE:
nodeQueue.Enqueue(new Tuple<TNode, int>((TNode)parentNode.Left, nodeDepth));
在什麼情況下可以parentNode.Left是東西,是不能分配給TNODE(給出TNODE被約束型BTreeNode或派生的)。
換句話說,這個函數在什麼情況下會導致InvalidCastException?如果沒有一個,那麼爲什麼編譯器需要顯式的轉換?
編輯:我覺得我確定與改變實施類似:
TNode leftNode = parentNode.Left as TNode;
Debug.Assert(leftNode != null || parentNode.Left == null, "Left child is more derived.");
if (leftNode != null)
nodeQueue.Enqueue(new Tuple<TNode, int>(leftNode, nodeDepth));
剛剛意識到了這個問題。回想起來似乎很明顯! – tintoy