繁体   English   中英

一个简单的状态机,使用C#中的Static类通过事件通知其他订阅者

[英]A Simple State Machine using a Static class in C# to notify other subscribers via Events

我一直在尝试为我的应用程序编写一个简单的静态类状态机,以便在系统状态发生变化时通知其他控件和代码。 我想我几乎拥有它,但我遇到了一个小问题,我不知道如何解决。

这是代码:

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

我遇到的问题是这一行:

 OnStateChange(this, sysInfo);

具体来说,“this”这个词是非法的。 我理解为什么:“this”应该引用一个实例化对象(不是静态类)的self。

我宁愿为我的状态机安装一个静态类,而不是一个可以实例化多个副本的静态类。 (并不是说它会是一件坏事,但我觉得它使代码更清晰,有一个静态类。)

那我该怎么办呢?

更新:

作为后续行动,我选择Jon Skeet作为正确的答案,因为问题更多的是关于我采取的方法,而不是我所遇到的技术故障。 虽然,下面几乎所有其他答案都解决了我正在处理的技术故障。

奇怪的是,当我和我的同事一起审阅我写的应用程序时,她指出程序应该跟踪服务器连接的状态以及正在完成的工作的状态。 (是的,弗吉尼亚州,这意味着我需要2台状态机... Ergo,从上面的代码中删除所有“静态”关键字并使其成为常规类是智能方法。)

再次感谢大家!

你为什么想要一个静态类? 它是一个状态机 - 它有状态 - 自然建议使用非静态类。 如果你真的想要,你总是可以有一个静态变量引用它的单个实例。

基本上,你的直觉在我看来是不正确的 - 拥有一个普通的类会使代码比静态的更干净。 静态类应该很少有任何状态 - 可能是缓存(尽管甚至可疑),或用于诊断目的的计数器等。尝试用对象而不是来思考。 拥有两个独立的状态机,具有不同的当前状态和可能不同的事件处理程序是否有意义? 很容易想象就是这种情况 - 这意味着很容易为测试等创建新实例(它还允许独立测试并行运行。)因此,在机器实例中具有状态是很自然的。

有些人认为应该没有静态方法, 没有静态类等。我认为这有点远,但你应该总是至少考虑引入静态的可测试性影响。

当您在静态范围内工作时,不能使用“this”,例如静态类或静态方法。

你有两个选择。 您可以为“sys”参数传递null 实际上,在静态类的情况下,此参数实际上没用,因为“sender”始终是静态类。

或者,您可能需要考虑使您的状态通知符成为单例 这将允许您拥有非静态类的单个实例。 如果未来的需求发生变化,这确实具有使得更容易转换到非静态实现的一个优点。


此外,在发起此活动之前,您确实应该检查以确保有订阅者。 不这样做可能会导致问题:

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

修改你的代表:

从:

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

至:

public static delegate void StateChangeHandler(SysInfoEventArgs sysStateInfo);

我要改变这段代码:

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

至:

public static event Action<SysInfoEventArgs> OnStateChange;

如果你真的想保留静态类并使用object sender的语义,那么传递的正确的东西就是typeof(Sys) 这也类似于静态类上的(旧的和罕见的)锁定习语。

但这只是迂腐,因为事件处理程序永远不会使用该值,实际上null也可以正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM