Does C# include finite state machines?
Asked Answered
R

8

29

I've recently read about the boost::statechart library (finite state machines) and I loved the concept.

Does C# have a similar mechanism ? Or can it be implemented using a specific design pattern?

Ripping answered 10/9, 2009 at 18:40 Comment(0)
I
0

Yes, C# has iterator blocks which are compiler-generated state machines.

If you wish to implement you own state machine you can create custom implementations of the IEnumerable<T> and IEnumerator<T> interfaces.

Both of these approaches highlight the .NET framework's implementation of the iterator pattern.

Iciness answered 10/9, 2009 at 18:43 Comment(7)
Iterators are by far no state machines. Some basic concepts of FSMs are states, transitions, transition guards, actions and hierarchical states. These are NOT explicit in the iterator blocks, so i do not agree that this is a implementation of FSM.Superiority
Iterator blocks are implemented as state machines, but that does not mean they are suited for building an arbitrary state machine. Erik Lippert makes this point here: #1195353Ricoricochet
@Gabe - That is correct which is why I pointed out the IEnumerable<T> and IEnumerator<T> interfaces.Iciness
Also I didn't claim that iterator blocks should be used to implement a state machine, simply that they are an implementation of a state machine that the compiler generates for you.Iciness
The fact that Iterators use a FSM is irrelevant to the question at hand. The OP wants to create his own.Inhumanity
One of the coolest uses of iterators as FSM I have seen has been uses as asynchronous iterators for asynchronous programming - most popular of which is Jeffrey Richter's AsyncEnumerator. Maybe this is language construct abuse, but it represents the easiest way I have seen by far to write asynchronous code for linear workflows in C#.Halmahera
There's an even simpler state machine in C#: learn.microsoft.com/en-us/dotnet/api/…Pantalets
A
20

.NET 4 Update 1 now supports it in the following class: System.Activities.Statements.StateMachine

Here is a tutorial on how to use it. Here's a hands on lab.

Acculturation answered 30/7, 2011 at 11:36 Comment(0)
S
8

Workflow Foundation (.NET 3.0) has a state machine workflow. 4.0 doesn't have exactly the same thing currently, but you can definitely create a state machine workflow using 4.0.

Sussman answered 10/9, 2009 at 19:0 Comment(1)
.NET 4 Platform Update comes with state machine support for WF4, now.Sussman
P
6

I maintain an open-source project which implements (among other things) a generic finite state machine for .NET. It is built on top of QuickGraph, so you get many graph-analysis algorithms for free.

See this page for more information about the project, and specifically "Jolt.Automata : Finite State Machines" for more information about the feature.

Prepositive answered 7/12, 2009 at 20:30 Comment(0)
J
5

Check out Stateless -> http://code.google.com/p/stateless/. Its a lightweight alternative to the heavier WWF.

Here's a couple of articles by the author of the tool:

State Machines in Domain Models

Parameterised Triggers and Re-entrant States in Stateless

Jovi answered 6/12, 2011 at 4:25 Comment(1)
Broken link. The project now lives here: github.com/dotnet-state-machine/statelessKirsch
S
2

The things that come near to FSMs are workflows in .NET 3.5, however, also workflows are not exactly FSMs.

The power of using FSMs is that you can create them explicitly in your code, having less chance of creating bugs. Besides, of course some systems are FSMs by nature, so it is more natural to code them like so.

Superiority answered 10/9, 2009 at 19:4 Comment(2)
FSM stands for Flying Spaghetti Monster. I think you answered the wrong question.Ricoricochet
I'm pretty sure that he wasn't referring to the Flying Spagetti Monster and instead was referring to Finite State Machine.Iamb
O
1

Windows Workflow Foundation (WF) that is part of the base class library in 3.0 and 3.5 includes a state-machine workflow design to manage state machines for your applications.

They have completely rewritten workflow for the upcoming 4.0 release, and the new WF 4.0 classes do not natively support state-machines, but all of the 3.0/3.5 classes are still fully supported under 4.0.

Ouidaouija answered 7/12, 2009 at 20:52 Comment(0)
I
0

Yes, C# has iterator blocks which are compiler-generated state machines.

If you wish to implement you own state machine you can create custom implementations of the IEnumerable<T> and IEnumerator<T> interfaces.

Both of these approaches highlight the .NET framework's implementation of the iterator pattern.

Iciness answered 10/9, 2009 at 18:43 Comment(7)
Iterators are by far no state machines. Some basic concepts of FSMs are states, transitions, transition guards, actions and hierarchical states. These are NOT explicit in the iterator blocks, so i do not agree that this is a implementation of FSM.Superiority
Iterator blocks are implemented as state machines, but that does not mean they are suited for building an arbitrary state machine. Erik Lippert makes this point here: #1195353Ricoricochet
@Gabe - That is correct which is why I pointed out the IEnumerable<T> and IEnumerator<T> interfaces.Iciness
Also I didn't claim that iterator blocks should be used to implement a state machine, simply that they are an implementation of a state machine that the compiler generates for you.Iciness
The fact that Iterators use a FSM is irrelevant to the question at hand. The OP wants to create his own.Inhumanity
One of the coolest uses of iterators as FSM I have seen has been uses as asynchronous iterators for asynchronous programming - most popular of which is Jeffrey Richter's AsyncEnumerator. Maybe this is language construct abuse, but it represents the easiest way I have seen by far to write asynchronous code for linear workflows in C#.Halmahera
There's an even simpler state machine in C#: learn.microsoft.com/en-us/dotnet/api/…Pantalets
B
-1

Other alternative in this repo https://github.com/lingkodsoft/StateBliss used fluent syntax, supports triggers.

    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
    }
}

Bolton answered 30/7, 2019 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.