[英]Events and Delegates in c# : How to use Events & Delegates to Notify One class about changes in other class
[英]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.