[英]What's the best(when performance matters) way to implement a state machine in C#?
我想出了以下選項:
使用goto語句:
Start:
goto Data
Data:
goto Finish
Finish:
;
使用switch語句:
switch(m_state) {
case State.Start:
m_state = State.Data;
break;
case State.Data:
m_state = State.Finish;
break;
case State.Finish:
break;
}
使用goto和switch一起:
switch(m_state) {
case State.Start:
goto case State.Data2;
case State.Data1:
goto case State.Finish;
case State.Data2:
m_state = State.Data1;
//call to a function outside the state machine
//that could possibly change the state
break;
case State.Finish:
break;
}
我更喜歡使用goto語句的第一個選項,因為它更快,更簡潔。 但我不確定它是不是最好的選擇。 表現明智,但是當談到可讀性我不知道。 這就是我問這個問題的原因。 您更喜歡哪個選項?為什么?
我更喜歡相互調用/遞歸函數。 要適應你的例子:
returnvalue Start() {
return Data();
}
returnvalue Data() {
return Finish();
}
returnvalue Finish() {
…
}
從理論上講,這可以完全內聯,因此編譯器輸出等同於你的goto
解決方案(因此速度相同)。 實際上, C#編譯器/ JITter可能不會這樣做 。 但是,由於該解決方案是大大更具可讀性(好吧,恕我直言),我只會用替換它goto
一個非常仔細的標桿證明它是在速度方面的確遜色,或出現堆棧溢出(在此簡單的解決方案之后,解決方案但是更大的自動機會遇到這個問題)。
即便如此,我肯定會堅持使用goto case
解決方案。 為什么? 因為那么你的整個凌亂goto
面食是公包封的嵌段結構(內部switch
塊)和您的面條不會裂傷的代碼的其余部分,從而防止波倫亞。
總之 :功能變體很清楚,但通常容易出問題。 goto
解決方案很麻煩。 只有goto case
提供了一個干凈,高效的解決方案。 如果性能確實是最重要的(並且自動機是瓶頸),那么請選擇結構化的goto case
變體。
切換goto的優點是你在變量中有狀態,而不僅僅是在指令指針中。
使用goto方法,狀態機必須是控制其他所有內容的主循環,因為你不會因為丟失狀態而退出它。
使用切換方法,狀態機是隔離的,您可以到任何想要處理外部事件的地方。 當你返回狀態機時,它會繼續在yuu停止的地方繼續。 您甚至可以並排運行多個狀態機,這是goto版本無法實現的。
我不確定你在第三種方案中走向何方,它看起來就像是第一種無用的開關。
如果您希望將狀態機轉換邏輯分解為單獨的函數,則只能使用switch語句執行此操作。
switch(m_state) {
case State.Start:
m_state = State.Data;
break;
case State.Data:
m_state = ComputeNextState();
break;
case State.Finish:
break;
}
它也更具可讀性,並且switch語句(與Goto相比)的開銷只會在極少數情況下產生性能差異。
編輯:
您可以使用“轉到大小寫”來提高性能:
switch(m_state) {
case State.Start:
m_state = State.Data; // Don't forget this line!
goto case State.Data;
case State.Data:
m_state = ComputeNextState();
break;
case State.Finish:
break;
}
但是,您可能會忘記更新狀態變量。 這可能會在以后導致細微的錯誤(因為你假設“m_state”被設置),所以我建議避免它。
我個人更喜歡第二個與goto,因為第一個將需要不必要的循環步驟(例如)進入新狀態
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.