Pre*_*zel 4 c# events static class state-machine
我一直在尝试为我的应用程序编写一个简单的静态类状态机,以便在系统状态发生变化时通知其他控件和代码.我想我几乎拥有它,但我遇到了一个小问题,我不知道如何解决.
这是代码:
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是这一行:
OnStateChange(this, sysInfo);
Run Code Online (Sandbox Code Playgroud)
具体来说,"this"这个词是非法的.我理解为什么:"this"应该引用一个实例化对象(不是静态类)的self.
我宁愿为我的状态机安装一个静态类,而不是一个可以实例化多个副本的静态类.(并不是说它会是一件坏事,但我觉得它使代码更清晰,有一个静态类.)
那我该怎么做呢?
更新:
作为后续行动,我选择Jon Skeet作为正确的答案,因为问题更多的是关于我采取的方法,而不是我所遇到的技术故障.虽然,下面几乎所有其他答案都解决了我正在处理的技术故障.
奇怪的是,当我和我的同事一起审阅我写的应用程序时,她指出程序应该跟踪服务器连接的状态以及正在完成的工作的状态.(是的,弗吉尼亚州,这意味着我需要2台状态机... Ergo,从上面的代码中删除所有"静态"关键字并使其成为常规类是智能方法.)
再次感谢大家!
Jon*_*eet 14
你为什么想要一个静态类?它是一个状态机 - 它有状态 - 自然建议使用非静态类.如果你真的想要,你总是可以有一个静态变量引用它的单个实例.
基本上,你的直觉在我看来是不正确的 - 拥有一个普通的类会使代码比静态的更干净.静态类应该很少有任何状态 - 可能是缓存(尽管甚至可疑),或用于诊断目的的计数器等.尝试用对象而不是类来思考.拥有两个独立的状态机,具有不同的当前状态和可能不同的事件处理程序是否有意义?很容易想象就是这种情况 - 这意味着很容易为测试等创建新实例(它还允许独立测试并行运行.)因此,在机器实例中具有状态是很自然的.
有些人认为应该没有静态方法,没有静态类等.我认为这有点远,但你应该总是至少考虑引入静态的可测试性影响.
当您在静态范围内工作时,不能使用"this",例如静态类或静态方法.
你有两个选择.您可以传递null
"sys"参数.实际上,在静态类的情况下,此参数实际上没用,因为"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);
}
}
Run Code Online (Sandbox Code Playgroud)