Imagine following scenario. You are minding your own business and calling some nice COM function. Suddenly you got COMException going on. And it is not your fault. Code is perfect, women are nice and all you have in that line is simple check (e.g. myCom.Show(handle) == NativeMethods.S_OK
). To make things worse you get also “The operation was canceled by the user. (Exception from HRESULT: 0x800704C7)” (or something similar).
Ok, you admit to your self, I did press the cancel button. But this function clearly says that it will return code different than S_OK. It never says anything about any exceptions. And can COM even raise exception in my code? Aha! Real culprit must sit in COM interop layer.
Precise dose of googling (or binging) gives source of misery. Some helpful soul in .NET design team decided that COMException will be thrown whenever HRESULT returns anything that is not success. And thus, something that ought to handled by simple conditional statement (formerly known as if) is now trashing our carefully woven code. Fortunately, smart guy from same team gave us antidote in form of PreserveSig attribute. Small dose of said attribute at function call alleviates all issues.
P.S. Normal person would just say to apply PreserveSig attribute to any function whose result code is handled within your code.
P.P.S. Even smarter person would give you the code:
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig()]
uint Show([In, Optional] IntPtr hwndOwner);