c# - implementando una máquina de estado usando la palabra clave "rendimiento"
yield state-machines (4)
Es factible pero es una mala idea. Los bloques de iteradores se crearon para ayudarlo a escribir iteradores personalizados para colecciones, no para resolver el problema de propósito general de implementar máquinas de estado.
Si desea escribir una máquina de estados, simplemente escriba una máquina de estados. No es dificil. Si desea escribir muchas máquinas de estado, escriba una biblioteca de métodos de ayuda útiles que le permitan representar de forma clara las máquinas de estado y luego use su biblioteca. Pero no abuses de un constructo de lenguaje destinado a algo completamente diferente que simplemente usa máquinas de estados como un detalle de implementación. Eso hace que su código de máquina de estado sea difícil de leer, entender, depurar, mantener y extender.
(Y, por cierto, hice una doble toma al leer tu nombre. ¡Uno de los diseñadores de C # también se llama Matt Warren!)
¿Es factible usar la palabra clave de rendimiento para implementar una máquina de estado simple como se muestra aquí ? A mí me parece que el compilador de C # ha hecho el trabajo duro por usted, ya que implementa internamente una máquina de estados para hacer que la declaración de rendimiento funcione.
¿Puede realizar una copia del trabajo que el compilador ya está haciendo y lograr que implemente la mayor parte de la máquina de estado para usted?
¿Alguien ha hecho esto, es técnicamente posible?
Los bloques de iteradores sí implementan máquinas de estado, pero el bit difícil es obtener la siguiente entrada. ¿Cómo vas a saber dónde moverte? Supongo que podrías tener algún tipo de variable de "transición actual" compartida, pero eso es un poco complicado.
Si no necesita ninguna entrada (p. Ej., Su máquina de estado solo está alternando entre estados), entonces es fácil, pero ese no es el tipo interesante :)
¿Puede describir el tipo de máquina de estado que le interesa?
Sí, es absolutamente posible y fácil de hacer. Puede disfrutar utilizando construcciones de flujo de control ( for
, foreach
, while
, ... goto
(el uso de goto
adapta particularmente a este escenario;)) junto con los yield
para construir una.
IEnumerator<State> StateMachine
(Func<int> currentInput /* gets current input from IO port */,
Func<int> currentOutput) {
for (;;) {
if ((currentInput() & 1) == 0)
yield return new State("Ready");
else {
if (...) {
yield return new State("Expecting more data");
SendOutput(currentOutput());
while ((currentInput() & 2) != 0) // while device busy
yield return new State("Busy");
else if (...) { ... }
}
}
}
// consumer:
int data;
var fsm = StateMachine(ReadFromIOPort, () => data);
// ...
while (fsm.Current != "Expecting more data")
fsm.MoveNext();
data = 100;
fsm.MoveNext();
Si bien esta no es una máquina de estado en el sentido clásico, el artículo sobre Micro Threading basado en iterador utiliza el rendimiento de forma creativa para acciones basadas en estado.
IEnumerable Patrol ()
{
while (alive){
if (CanSeeTarget ()) {
yield return Attack ();
} else if (InReloadStation){
Signal signal = AnimateReload ();
yield return signal;
} else {
MoveTowardsNextWayPoint ();
yield return TimeSpan.FromSeconds (1);
};
}
yield break;
}