更新:
再次感谢你的例子,它们对我很有帮助,我并不是说
夺走他们的一切。
Aren't the currently given examples, as far as I understand them & state-machines, only half of what we usually understand by a state-machine?
In the sense that the examples do change state but that's only represented by changing the value of a variable (and allowing different value- changes in different states), while usually, a state machine should also change its behavior, and behavior not (only) in the sense of allowing different value changes for a variable depending on the state, but in the sense of allowing different methods to be executed for different states.
还是我对状态机及其常用用法有误解?
最初的问题:
我发现了关于c#中的状态机和迭代器块的讨论,以及用于创建状态机和c#的工具,所以我发现了很多抽象的东西,但作为一个新手,所有这些都有点令人困惑。
因此,如果有人能提供一个c#源代码-示例,实现一个简单的状态机,可能只有3,4个状态,那就太好了,只是为了了解它的要点。
finitestatemmachine是一个简单的状态机,用c# Link编写
使用我的库finitestatemmachine的优点:
定义一个“context”类,向外界呈现一个单独的接口。
定义一个State抽象基类。
将状态机的不同“状态”表示为state基类的派生类。
在适当的State派生类中定义特定于状态的行为。
在“context”类中维护一个指向当前“state”的指针。
要更改状态机的状态,请更改当前的“state”指针。
下载DLL下载
LINQPad上的示例:
void Main()
{
var machine = new SFM.Machine(new StatePaused());
var output = machine.Command("Input_Start", Command.Start);
Console.WriteLine(Command.Start.ToString() + "-> State: " + machine.Current);
Console.WriteLine(output);
output = machine.Command("Input_Pause", Command.Pause);
Console.WriteLine(Command.Pause.ToString() + "-> State: " + machine.Current);
Console.WriteLine(output);
Console.WriteLine("-------------------------------------------------");
}
public enum Command
{
Start,
Pause,
}
public class StateActive : SFM.State
{
public override void Handle(SFM.IContext context)
{
//Gestione parametri
var input = (String)context.Input;
context.Output = input;
//Gestione Navigazione
if ((Command)context.Command == Command.Pause) context.Next = new StatePaused();
if ((Command)context.Command == Command.Start) context.Next = this;
}
}
public class StatePaused : SFM.State
{
public override void Handle(SFM.IContext context)
{
//Gestione parametri
var input = (String)context.Input;
context.Output = input;
//Gestione Navigazione
if ((Command)context.Command == Command.Start) context.Next = new StateActive();
if ((Command)context.Command == Command.Pause) context.Next = this;
}
}
我在这里发布了另一个答案,因为这是从不同的角度来看状态机;非常视觉。
我最初的答案是经典的命令式代码。我认为它在代码运行时非常直观,因为数组使得状态机的可视化变得简单。缺点是你必须把这些都写下来。Remos的回答减轻了编写样板代码的工作量,但远没有那么直观。还有第三种选择;画状态机。
如果您正在使用。net,并且可以将运行时版本4作为目标,那么您可以选择使用工作流的状态机活动。从本质上讲,它们允许您绘制状态机(就像Juliet的图一样),并让WF运行时为您执行它。
有关更多细节,请参阅MSDN文章使用Windows Workflow Foundation构建状态机,以及最新版本的CodePlex站点。
这是我在瞄准。net时更喜欢的选项,因为它很容易看到、更改和向非程序员解释;俗话说,图片胜过千言万语!
不确定我是否错过了重点,但我认为这里没有一个答案是“简单的”状态机。我通常所说的简单状态机是使用一个内部有开关的循环。这就是我们在PLC /微芯片编程或C/ c++编程中使用的方法。
优点:
容易写。不需要特殊的物品和东西。你甚至不需要面向对象。
当它很小的时候,很容易理解。
缺点:
当有很多状态时,可能会变得相当大,很难阅读。
它是这样的:
public enum State
{
First,
Second,
Third,
}
static void Main(string[] args)
{
var state = State.First;
// x and i are just examples for stuff that you could change inside the state and use for state transitions
var x = 0;
var i = 0;
// does not have to be a while loop. you could loop over the characters of a string too
while (true)
{
switch (state)
{
case State.First:
// Do sth here
if (x == 2)
state = State.Second;
// you may or may not add a break; right after setting the next state
// or do sth here
if (i == 3)
state = State.Third;
// or here
break;
case State.Second:
// Do sth here
if (x == 10)
state = State.First;
// or do sth here
break;
case State.Third:
// Do sth here
if (x == 10)
state = State.First;
// or do sth here
break;
default:
// you may wanna throw an exception here.
break;
}
}
}
如果它真的应该是一个状态机,你调用的方法会根据你所处的状态做出不同的反应:状态设计模式是更好的方法