Une machine simple d'État en utilisant une classe statique en C # pour informer les autres abonnés via des événements

StackOverflow https://stackoverflow.com/questions/2411803

Question

J'ai essayé d'écrire simple État classe statique Machine pour ma demande d'informer les autres contrôles et le code lorsque les changements d'état du système. Et je crois avoir à peu près, mais je suis en cours d'exécution dans un petit problème que je ne suis pas sûr de savoir comment contourner.

Voici le code:

// An enum denoting the 3 States
public enum Status { Error = -1, Working, Ready }

// The main state change class
public static class Sys
{
    // system status
    private static Status state;

    // delegate and event
    public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);
    public static event StateChangeHandler OnStateChange;

    public static Status State
    {
        get { return state; }
        set
        {
            SysInfoEventArgs sysInfo = new SysInfoEventArgs(state, value);
            state = value;
            OnStateChange(this, sysInfo);
        }
    }
}

/// <summary>Contains previous and current state info</summary>
public class SysInfoEventArgs : EventArgs
{
    public readonly Status oldState;
    public readonly Status newState;
    public SysInfoEventArgs(Status oldState, Status newState)
    {
        this.oldState = oldState;
        this.newState = newState;
    }
}

Le problème que j'ai est avec cette ligne:

 OnStateChange(this, sysInfo);

Plus précisément, le mot « ce » est illégal. Et je comprends pourquoi: « ce » est censé se référer à soi-même d'un objet instancié (pas une classe statique)

.

Je préférerais avoir une classe statique pour ma machine d'état plutôt que celui que je peux instancier plusieurs copies de. (Non pas que ce serait une mauvaise chose, mais je pense qu'il rend le code plus propre ayant une classe statique.)

Alors, comment suis-je censé travailler cela?

Mise à jour:

En tant que suivi, je choisi la réponse de Jon Skeet comme correct parce que la question était plus sur l'approche que je prenais, plutôt que d'une défaillance technique que je faisais. Bien que, à peu près toutes les autres réponses ci-dessous résoudre le problème technique que je traitais.

Étrangement, comme je passais en revue avec mon collègue l'application que je l'ai écrit, elle a souligné que le programme devrait probablement suivre à la fois l'état de la connexion du serveur ainsi que l'état du travail accompli. (Oui, Virginie, cela signifie que je besoin de 2 machines d'état ... Ergo, supprimer tous les mots clés « statiques » du code ci-dessus et en faire une classe régulière était l'approche intelligente.)

Merci encore, tout le monde!

Était-ce utile?

La solution

Pourquoi voudriez-vous une classe statique? Il est un État la machine - qui suggère naturellement en utilisant une classe non statique - il a état . Vous pouvez toujours avoir une variable statique se référant à une seule instance de celui-ci si vous voulez vraiment.

En fait, votre instinct est incorrect, à mon avis - avoir une classe normale rendrait le code plus propre que statique. classes statiques devraient très rarement avoir tout Etat du tout - peut-être un cache (bien que même c'est douteux), ou des compteurs à des fins de diagnostic, etc. Essayez de penser en termes de objets des classes au lieu de . Est-il logique d'avoir deux machines d'état séparés, avec un autre état actuel et peut-être différents gestionnaires d'événements? Il est facile d'imaginer que ce soit le cas - et cela signifie qu'il est facile de créer de nouvelles instances pour les tests, etc. (Il permet également des tests indépendants de fonctionner en parallèle.) Avoir l'état dans une instance de la machine est donc un ajustement naturel

Il y a des gens qui pensent qu'il devrait y avoir pas méthodes statiques, pas classes statiques etc. Je pense que c'est de prendre un peu loin, mais vous devez toujours au moins considérer l'impact de l'introduction de la testabilité statics.

Autres conseils

Vous ne pouvez pas utiliser « ce » lorsque vous travaillez dans un cadre statique, comme une classe statique ou une méthode statique.

Vous avez deux options. Vous pouvez passer null pour le paramètre « sys ». Vraiment, ce paramètre, dans le cas d'une classe statique, est vraiment pas utile, puisque l ' « émetteur » est toujours la classe statique.

Vous voudrez peut-être envisager de faire votre état notificateur un singleton . Cela vous permettra d'avoir une seule instance d'une classe non statique. Cela a le seul avantage de faciliter la transition vers une mise en œuvre non statique si les besoins futurs changements, aussi bien.


En outre, vous devriez vraiment vérifier pour vous assurer qu'il ya des abonnés avant de lever cet événement. Ne pas le faire pourrait causer des problèmes:

public static Status State
{
    get { return state; }
    set
    {
        SysInfoEventArgs sysInfo = new SysInfoEventArgs(state, value);
        state = value;
        var handler = OnStateChange;
        if (handler != null)
            handler(null, sysInfo);
    }
}

Modifier votre délégué:

à partir de:

public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);

à:

public static delegate void StateChangeHandler(SysInfoEventArgs sysStateInfo);

Je changerais ce code:

public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);
public static event StateChangeHandler OnStateChange;

à:

public static event Action<SysInfoEventArgs> OnStateChange;

Si vous voulez vraiment garder la classe statique et utiliser la sémantique de object sender, alors la meilleure chose à passer serait typeof(Sys). Ceci est également analogue à l'idiome de verrouillage (anciens et rares) sur une classe statique.

Mais c'est juste d'être pointilleux, parce que le gestionnaire d'événements ne sera jamais utiliser cette valeur, et dans la pratique null fonctionnerait aussi bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top