C# 是不是包含有限状态机?

Posted

技术标签:

【中文标题】C# 是不是包含有限状态机?【英文标题】:Does C# include finite state machines?C# 是否包含有限状态机? 【发布时间】:2010-11-27 06:40:36 【问题描述】:

我最近阅读了有关 boost::statechart 库(有限状态机)的信息,我喜欢这个概念。

C# 有类似的机制吗?还是可以使用特定的设计模式来实现?

【问题讨论】:

【参考方案1】:

此回购中的其他替代方案https://github.com/lingkodsoft/StateBliss 使用流畅的语法,支持触发器。

    public class BasicTests
    
        [Fact]
        public void Tests()
        
            // Arrange
            StateMachineManager.Register(new []  typeof(BasicTests).Assembly ); //Register at bootstrap of your application, i.e. Startup
            var currentState = AuthenticationState.Unauthenticated;
            var nextState = AuthenticationState.Authenticated;
            var data = new Dictionary<string, object>();

            // Act
            var changeInfo = StateMachineManager.Trigger(currentState, nextState, data);

            // Assert
            Assert.True(changeInfo.StateChangedSucceeded);
            Assert.Equal("ChangingHandler1", changeInfo.Data["key1"]);
            Assert.Equal("ChangingHandler2", changeInfo.Data["key2"]);
        

        //this class gets regitered automatically by calling StateMachineManager.Register
        public class AuthenticationStateDefinition : StateDefinition<AuthenticationState>
        
            public override void Define(IStateFromBuilder<AuthenticationState> builder)
            
                builder.From(AuthenticationState.Unauthenticated).To(AuthenticationState.Authenticated)
                    .Changing(this, a => a.ChangingHandler1)
                    .Changed(this, a => a.ChangedHandler1);

                builder.OnEntering(AuthenticationState.Authenticated, this, a => a.OnEnteringHandler1);
                builder.OnEntered(AuthenticationState.Authenticated, this, a => a.OnEnteredHandler1);

                builder.OnExiting(AuthenticationState.Unauthenticated, this, a => a.OnExitingHandler1);
                builder.OnExited(AuthenticationState.Authenticated, this, a => a.OnExitedHandler1);

                builder.OnEditing(AuthenticationState.Authenticated, this, a => a.OnEditingHandler1);
                builder.OnEdited(AuthenticationState.Authenticated, this, a => a.OnEditedHandler1);

                builder.ThrowExceptionWhenDiscontinued = true;
            

            private void ChangingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            
                var data = changeinfo.DataAs<Dictionary<string, object>>();
                data["key1"] = "ChangingHandler1";
            

            private void OnEnteringHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            
                // changeinfo.Continue = false; //this will prevent changing the state
            

            private void OnEditedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
                            
            

            private void OnExitedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
                            
            

            private void OnEnteredHandler1(StateChangeInfo<AuthenticationState> changeinfo)
                            
            

            private void OnEditingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            
            

            private void OnExitingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            
            

            private void ChangedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
            
            
        

        public class AnotherAuthenticationStateDefinition : StateDefinition<AuthenticationState>
        
            public override void Define(IStateFromBuilder<AuthenticationState> builder)
            
                builder.From(AuthenticationState.Unauthenticated).To(AuthenticationState.Authenticated)
                    .Changing(this, a => a.ChangingHandler2);

            

            private void ChangingHandler2(StateChangeGuardInfo<AuthenticationState> changeinfo)
            
                var data = changeinfo.DataAs<Dictionary<string, object>>();
                data["key2"] = "ChangingHandler2";
            
        
    

    public enum AuthenticationState
    
        Unauthenticated,
        Authenticated
    


【讨论】:

【参考方案2】:

查看无状态 -> http://code.google.com/p/stateless/。它是较重的 WWF 的轻量级替代品。

以下是该工具作者的几篇文章:

State Machines in Domain Models

Parameterised Triggers and Re-entrant States in Stateless

【讨论】:

【参考方案3】:

.NET 4 Update 1 现在在以下类中支持它: System.Activities.Statements.StateMachine

这是tutorial on how to use it。 这是hands on lab。

【讨论】:

【参考方案4】:

我维护了一个开源项目,它实现了(除其他外)一个通用的 .NET 有限状态机。它建立在QuickGraph 之上,因此您可以免费获得许多图形分析算法。

有关该项目的更多信息,请参阅this page,特别是“Jolt.Automata : Finite State Machines”以了解有关该功能的更多信息。

【讨论】:

【参考方案5】:

作为 3.0 和 3.5 中基类库的一部分的 Windows Workflow Foundation (WF) 包含一个状态机工作流设计,用于管理应用程序的状态机。

他们为即将发布的 4.0 版本完全重写了工作流程,并且新的 WF 4.0 类本身不支持状态机,但 4.0 下仍然完全支持所有 3.0/3.5 类。

【讨论】:

【参考方案6】:

接近 FSM 的是 .NET 3.5 中的工作流,但是,工作流也不完全是 FSM。

使用 FSM 的强大之处在于您可以在代码中显式地创建它们,从而减少产生错误的机会。此外,当然有些系统本质上是 FSM,所以这样编码更自然。

【讨论】:

FSM 代表飞行意大利面怪物。我认为您回答了错误的问题。 我很确定他指的不是 Flying Spagetti Monster,而是指有限状态机。【参考方案7】:

Workflow Foundation (.NET 3.0) 有一个状态机工作流。 4.0 目前没有完全相同的东西,但是您绝对可以使用 4.0 创建状态机工作流。

【讨论】:

.NET 4 平台更新现在带有对 WF4 的状态机支持。【参考方案8】:

是的,C# 有 iterator blocks,它们是编译器生成的状态机。

如果您希望实现自己的状态机,您可以创建 IEnumerable&lt;T&gt;IEnumerator&lt;T&gt; 接口的自定义实现。

这两种方法都突出了 .NET 框架对 iterator pattern 的实现。

【讨论】:

迭代器目前还不是状态机。 FSM 的一些基本概念是状态、转换、转换保护、动作和分层状态。这些在迭代器块中不是明确的,所以我不同意这是 FSM 的实现。 迭代器块被实现为状态机,但这并不意味着它们适合构建任意状态机。 Erik Lippert 在这里提出了这一点:***.com/questions/1194853/… 另外,我并没有声称应该使用迭代器块来实现状态机,只是说它们是编译器为您生成的状态机的实现。 迭代器使用 FSM 的事实与手头的问题无关。 OP 想要创建自己的。 我见过的 FSM 迭代器最酷的用途之一是用作异步编程的 asynchronous iterators - 其中最受欢迎的是 Jeffrey Richter 的 AsyncEnumerator。也许这是语言结构滥用,但它代表了迄今为止我所见过的用 C# 为线性工作流编写异步代码的最简单方法。

以上是关于C# 是不是包含有限状态机?的主要内容,如果未能解决你的问题,请参考以下文章

有限状态机

有限状态机FSM和层次状态机HSM

AI之有限状态机

(有限)状态机

动画状态机是有限状态机还是行为树

Verilog笔记.3.有限状态机