Proper way of raising events from C++/CLI?
我想知道从C ++ / CLI引发事件的正确方法是什么。 在C#中,应该首先复制处理程序,检查其是否不为null,然后调用它。 C ++ / CLI是否有类似的做法?
这还不是全部!您通常不必担心C ++ / CLI中的空事件处理程序。这些检查的代码已为您生成。考虑下面的普通C ++ / CLI类。
1 2 3 4 5 | public ref class MyClass { public: event System::EventHandler ^ MyEvent; }; |
如果编译此类,然后使用Reflector对其进行反汇编,则将获得以下c#代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class MyClass { // Fields private EventHandler <backing_store>MyEvent; // Events public event EventHandler MyEvent { [MethodImpl(MethodImplOptions.Synchronized)] add { this.<backing_store>MyEvent = (EventHandler) Delegate.Combine(this.<backing_store>MyEvent, value); } [MethodImpl(MethodImplOptions.Synchronized)] remove { this.<backing_store>MyEvent = (EventHandler) Delegate.Remove(this.<backing_store>MyEvent, value); } raise { EventHandler <tmp> = null; <tmp> = this.<backing_store>MyEvent; if (<tmp> != null) { <tmp>(value0, value1); } } } } |
通常的检查是在raise方法中进行的。除非您真的想要自定义行为,否则您应该像上面的类中那样声明您的事件,并在不担心使用null处理程序的情况下进行声明。
C ++ / CLI允许您在自定义事件处理程序中覆盖
为了更正,示例从MSDN改编而成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public delegate void f(int); public ref struct E { f ^ _E; public: void handler(int i) { System::Console::WriteLine(i); } E() { _E = nullptr; } event f^ Event { void add(f ^ d) { _E += d; } void remove(f ^ d) { _E -= d; } void raise(int i) { f^ tmp = _E; if (tmp) { tmp->Invoke(i); } } } static void Go() { E^ pE = gcnew E; pE->Event += gcnew f(pE, &E::handler); pE->Event(17); } }; int main() { E::Go(); } |
如果您的问题是加薪不是私人的,请像文档所说的那样显式实施:
http://msdn.microsoft.com/zh-CN/library/5f3csfsa.aspx
综上所述:
如果仅使用event关键字,则会创建一个"琐碎的"事件。编译器会为您生成添加/删除/提升和委托成员。生成的raise函数(如文档所说)检查nullptr。琐事记录在这里:
http://msdn.microsoft.com/zh-CN/library/4b612y2s.aspx
例如,如果您想"更多控制权"以将抬高设置为私有,则必须显式实现成员,如链接中所示。您必须为委托类型显式声明一个数据成员。然后,使用event关键字声明与事件相关的成员,如Microsoft示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // event keyword introduces the scope wherein I'm defining the required methods //"f" is my delegate type //"Event" is the unrealistic name of the event itself event f^ Event { // add is public (because the event block is public) //"_E" is the private delegate data member of type"f" void add(f ^ d) { _E += d; } // making remove private private: void remove(f ^ d) { _E -= d; } // making raise protected protected: void raise(int i) { // check for nullptr if (_E) { _E->Invoke(i); } } }// end event block |
罗y的,但确实如此。
-赖利