2
我必須實現一個表達式的調用圖,如Id = Id(Param);
,這不是問題。調用圖IEnumerator
現在我必須實現一個枚舉器,它在滿足順序依賴關係的調用中一次列出所有拓撲順序中的一個。
這就是麻煩。
這是調用圖一個簡單的節點:
class CallGraphNode
{
private string name;
public List<CallGraphNode> dependents = new List<CallGraphNode>();
public int dependencies;
private bool executed = false;
public bool Executable { get { return dependencies == 0; } }
public bool Executed { get { return executed; } set { executed = value; } }
public CallGraphNode(string name)
{
this.name = name;
dependencies = 0;
}
public override string ToString()
{
return name;
}
public void AddDependent(CallGraphNode n)
{
dependents.Add(n);
}
}
這是調用圖類本身:
class CallGraph : IEnumerable<List<CallGraphNode>>
{
public List<CallGraphNode> nodes = new List<CallGraphNode>();
public void AddNode(CallGraphNode n)
{
nodes.Add(n);
}
public static void Show(IEnumerable<CallGraphNode> n)
{
foreach (CallGraphNode node in n)
{
Console.Write("{0} ", node);
}
Console.WriteLine();
}
static IEnumerable<List<CallGraphNode>> EnumerateFunctions(List<CallGraphNode> executable, List<CallGraphNode> res)
{
if (executable.Count == 0)
yield return res;
else foreach (CallGraphNode n in executable)
{
if (!n.Executed)
res.Add(n);
List<CallGraphNode> next_executable = new List<CallGraphNode>(executable);
executable.Remove(n);
foreach (CallGraphNode m in n.dependents)
if (--m.dependencies == 0)
next_executable.Add(m);
foreach (List<CallGraphNode> others in EnumerateFunctions(next_executable, res))
yield return others;
foreach (CallGraphNode m in n.dependents)
m.dependencies++;
if (!n.Executed)
res.Remove(n);
}
}
IEnumerator<List<CallGraphNode>> IEnumerable<List<CallGraphNode>>.GetEnumerator()
{
List<CallGraphNode> executable = new List<CallGraphNode>();
foreach (CallGraphNode n in nodes)
if (n.Executable || n.Executed)
executable.Add(n);
List<CallGraphNode> output = new List<CallGraphNode>();
foreach (List<CallGraphNode> list in EnumerateFunctions(executable, output))
yield return list;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{ throw new NotImplementedException(); }
}
現在的問題是,它只是將無法正常工作。當我嘗試創建一個IEnumerator
併爲其分配GetEnumerator()
返回值,我得到一個鑄造的錯誤,這就是誠實跟我想象試圖這樣做的時候:
IEnumerator<List<CallGraphNode>> lt = cg.GetEnumerator();
然後我試着:
System.Collections.Generic.List<CallGraphNode>.Enumerator en = cg.nodes.GetEnumerator();
這可行,但方法EnumerateFunctions
永遠不會被調用,枚舉器只包含圖形節點的原始列表。
任何想法?
我選擇了明確的實現方式ñ,它像一個魅力工作,謝謝。但EnumerateFunctions方法永遠不會被調用。很奇怪。 – Cancer 2012-07-09 20:22:33
@ user1512923:你真的在迭代結果嗎?如果不是,那麼'GetEnumerator'方法中的* none *代碼將被調用。迭代器塊的一部分是代碼被懶惰地執行。 – 2012-07-09 21:33:46
感謝Jon,你是對的,我設法讓它工作迭代結果!我認爲代碼本來會被調用的。非常感謝 :) – Cancer 2012-07-09 22:19:47