我正在使用 C#、.NET 3.5.我了解如何利用事件,如何在我的班级中声明它们,如何从其他地方挂钩它们等等.一个人为的例子:
I'm using C#, .NET 3.5. I understand how to utilize events, how to declare them in my class, how to hook them from somewhere else, etc. A contrived example:
public class MyList
{
private List<string> m_Strings = new List<string>();
public EventHandler<EventArgs> ElementAddedEvent;
public void Add(string value)
{
m_Strings.Add(value);
if (ElementAddedEvent != null)
ElementAddedEvent(value, EventArgs.Empty);
}
}
[TestClass]
public class TestMyList
{
private bool m_Fired = false;
[TestMethod]
public void TestEvents()
{
MyList tmp = new MyList();
tmp.ElementAddedEvent += new EventHandler<EventArgs>(Fired);
tmp.Add("test");
Assert.IsTrue(m_Fired);
}
private void Fired(object sender, EventArgs args)
{
m_Fired = true;
}
}
然而,我不理解的是,当一个人声明一个事件处理程序时
However, what I do not understand, is when one declares an event handler
public EventHandler<EventArgs> ElementAddedEvent;
它从未被初始化 - 那么,ElementAddedEvent 究竟是什么?它指向什么?以下将不起作用,因为 EventHandler 从未初始化:
It's never initialized - so what, exactly, is ElementAddedEvent? What does it point to? The following won't work, because the EventHandler is never initialized:
[TestClass]
public class TestMyList
{
private bool m_Fired = false;
[TestMethod]
public void TestEvents()
{
EventHandler<EventArgs> somethingHappend;
somethingHappend += new EventHandler<EventArgs>(Fired);
somethingHappend(this, EventArgs.Empty);
Assert.IsTrue(m_Fired);
}
private void Fired(object sender, EventArgs args)
{
m_Fired = true;
}
}
我注意到有一个 EventHandler.CreateDelegate(...),但所有方法签名都表明这仅用于通过典型的 ElementAddedEvent += new EventHandler(MyMethod) 将 Delegates 附加到已经存在的 EventHandler.
I notice that there is an EventHandler.CreateDelegate(...), but all the method signatures suggest this is only used for attaching Delegates to an already existing EventHandler through the typical ElementAddedEvent += new EventHandler(MyMethod).
我不确定我正在尝试做的什么是否会有所帮助......但最终我想在 LINQ 中提出一个抽象的父 DataContext,它的孩子可以注册哪些表类型他们想要观察",所以我可以有诸如更新前和更新后之类的事件,但特定于类型.像这样的:
I'm not sure if what I am trying to do will help... but ultimately I'd like to come up with an abstract parent DataContext in LINQ whose children can register which table Types they want "observed" so I can have events such as BeforeUpdate and AfterUpdate, but specific to types. Something like this:
public class BaseDataContext : DataContext
{
private static Dictionary<Type, Dictionary<ChangeAction, EventHandler>> m_ObservedTypes = new Dictionary<Type, Dictionary<ChangeAction, EventHandler>>();
public static void Observe(Type type)
{
if (m_ObservedTypes.ContainsKey(type) == false)
{
m_ObservedTypes.Add(type, new Dictionary<ChangeAction, EventHandler>());
EventHandler eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
m_ObservedTypes[type].Add(ChangeAction.Insert, eventHandler);
eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
m_ObservedTypes[type].Add(ChangeAction.Update, eventHandler);
eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
m_ObservedTypes[type].Add(ChangeAction.Delete, eventHandler);
}
}
public static Dictionary<Type, Dictionary<ChangeAction, EventHandler>> Events
{
get { return m_ObservedTypes; }
}
}
public class MyClass
{
public MyClass()
{
BaseDataContext.Events[typeof(User)][ChangeAction.Update] += new EventHandler(OnUserUpdate);
}
public void OnUserUpdated(object sender, EventArgs args)
{
// do something
}
}
考虑到这一点让我意识到我并不真正了解事件背后发生的事情 - 我想了解:)
Thinking about this made me realize I don't really understand what's happening under the hod with events - and I would like to understand :)
我已经在 一篇文章,但这里是摘要,假设您对 代表 自己:
I've written this up in a fair amount of detail in an article, but here's the summary, assuming you're reasonably happy with delegates themselves:
对于类似字段的事件,有一些同步,否则添加/删除只需调用 Delegate.合并/删除以更改自动生成字段的值.这两个操作都分配给支持字段 - 请记住,委托是不可变的.换句话说,自动生成的代码很像这样:
For field-like events, there's some synchronization but otherwise the add/remove just call Delegate.Combine/Remove to change the value of the auto-generated field. Both of these operations assign to the backing field - remember that delegates are immutable. In other words, the autogenerated code is very much like this:
// Backing field
// The underscores just make it simpler to see what's going on here.
// In the rest of your source code for this class, if you refer to
// ElementAddedEvent, you're really referring to this field.
private EventHandler<EventArgs> __ElementAddedEvent;
// Actual event
public EventHandler<EventArgs> ElementAddedEvent
{
add
{
lock(this)
{
// Equivalent to __ElementAddedEvent += value;
__ElementAddedEvent = Delegate.Combine(__ElementAddedEvent, value);
}
}
remove
{
lock(this)
{
// Equivalent to __ElementAddedEvent -= value;
__ElementAddedEvent = Delegate.Remove(__ElementAddedEvent, value);
}
}
}
在您的情况下,生成字段的初始值为 null
- 如果删除所有订阅者,它将始终再次变为 null
,因为那是Delegate.Remove 的行为.
The initial value of the generated field in your case is null
- and it will always become null
again if all subscribers are removed, as that is the behaviour of Delegate.Remove.
如果你想要一个no-op"处理程序来订阅你的事件,以避免无效性检查,你可以这样做:
If you want a "no-op" handler to subscribe to your event, so as to avoid the nullity check, you can do:
public EventHandler<EventArgs> ElementAddedEvent = delegate {};
delegate {}
只是一个匿名方法,它不关心它的参数并且什么都不做.
The delegate {}
is just an anonymous method which doesn't care about its parameters and does nothing.
如果还有什么不清楚的地方,请询问,我会尽力帮助的!
If there's anything that's still unclear, please ask and I'll try to help!
这篇关于C# 事件如何在幕后工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!