C#事件实现(文章与reflection器)
public class EventsType {public event EventHandler> NewEvent;
public void SmthHappened(string data) { MyEventArgs eventArgs = new MyEventArgs(data); OnNewEvent(eventArgs); } private void OnNewEvent(MyEventArgs eventArgs) { EventHandler<MyEventArgs> tempEvent = NewEvent; if (tempEvent != null) { tempEvent(this, eventArgs); } } }
我期望C#编译器会像这样翻译NewEvent:
private EventHandler<MyEventArgs> _newEvent; public event EventHandler<MyEventArgs> NewEvent { [MethodImpl(MethodImplOptions.Synchronized)] add { _newEvent = (EventHandler<MyEventArgs>)Delegate.Combine(_newEvent, value); } [MethodImpl(MethodImplOptions.Synchronized)] remove { _newEvent = (EventHandler<MyEventArgs>)Delegate.Remove(_newEvent, value); } }
,但Reflector表示它是以这种方式实现的:
public event EventHandler<MyEventArgs> NewEvent { add { EventHandler<MyEventArgs> handler2; EventHandler<MyEventArgs> newEvent = this.NewEvent; do { handler2 = newEvent; EventHandler<MyEventArgs> handler3 = (EventHandler<MyEventArgs>) Delegate.Combine(handler2, value); newEvent = Interlocked.CompareExchange<EventHandler<MyEventArgs>>(ref this.NewEvent, handler3, handler2); } while (newEvent != handler2); } remove { EventHandler<MyEventArgs> handler2; EventHandler<MyEventArgs> newEvent = this.NewEvent; do { handler2 = newEvent; EventHandler<MyEventArgs> handler3 = (EventHandler<MyEventArgs>) Delegate.Remove(handler2, value); newEvent = Interlocked.CompareExchange<EventHandler<MyEventArgs>>(ref this.NewEvent, handler3, handler2); } while (newEvent != handler2); } }
拜托,smb解释我为什么会这样?
是的:基本上, C#4在这个领域做了一些改变 。 它使其无需锁定即可保证线程安全。 这不是唯一的变化 – 它还会改变对类中类字段事件的引用的解决方式:+ =和 – =现在通过“添加”和“删除”位而不是直接使用支持字段。
请注意,此更改会影响使用C#4编译器编译的代码,即使对于较旧的框架也是如此; 还有一些锁定更改只影响针对.NET 4编译的代码,因为它使用了一种新方法( Monitor.TryEnter(object, out bool)
)。
这个问题的答案很大程度上取决于您使用的版本。 多年来它经过了很多改进。 见http://blogs.msdn.com/b/cburrows/archive/2010/03/05/events-get-a-little-overhaul-in-c-4-part-i-locks.aspx
您期望的是一个简单的非线程安全实现。 像事件语法这样的字段总是提供线程安全语法(因此reflection器版本)。 请参阅此artcile以了解事件及其实施方式。
- 使用lambda表达式注册类型
- NetworkStream和TcpClient有多少缓冲区?
- 抛出了类型’System.Windows.Forms.AxHost + InvalidActiveXStateException’的exception
- 如何在每个循环周期中一步更新进度条? C#
- File.Delete在之前调用Image.FromFile时失败,尽管复制了加载的图像并破坏了原始图像
- 检查asp.net mvc 5中是否存在文件
- 在HangFire中设置“按需”唯一作业
- 表示字符文字时使用\ u和\ x有什么区别
- 用C#中的“Unit Separator”(0x1f)替换平面文件中的制表符(“\ t”)