-1

I'm writing a VC++/CLI <-> C# interface for a small unmanaged library. This library uses and implements WINAPI methods, so it mainly uses constructs as

DWORD getResult(__out LPWSTR* result);

Which means it does not return the requested result, but a statuscode, and the requested result is passed in the output parameter.

In C#, it seems, I have (at least) two ways of writing the interface:

  1. Dumbly "transpile" it to UInt32 getResult(String^% result);
  2. Make the interface more "object-oriented" by writing the method like String^ getResult(); throwing an (e.g.) Win32Exception when the statuscode of the managed call is non-zero (wrapping the statuscode in its NativeErrorCode member) (as shown e.g. here: Throwing a Win32Exception )

Of course this would not be that simple in case of multi-output functions, but let's say I don't care about them.

As I'm more used to OOP than to the VC++ style of coding, I would prefer option 2. However, I'm not sure if there aren't reasons that would render that a bad design choice (or if there isn't a third, even better way).

Community
  • 1
  • 1
Martin Pecka
  • 2,953
  • 1
  • 31
  • 40
  • The 95% odds are that this should be String^ GetResult() and an exception for any error code. Unless failure is likely and expected, then it should be renamed to TryGetResult(). – Hans Passant Jan 19 '16 at 02:31

1 Answers1

1

This is very much a matter of opinion--discussions about exception policy can go on forever.

I think you should mostly think about your framework's audience. If they're already accustomed to your unmanaged library then they might prefer the "dumb transpile" approach.

But if your users are typical C# developers then they'll expect #2, so that's what I'll cover from here on. A C# developer doesn't care that you're wrapping a native library and will just want your library to behave like every other .NET library.

So, assuming you go with #2, the Framework Design Guidelines book is a great place to start thinking about your exception design. Some stripped down excerpts are available on MSDN:

As for using Win32Exception, I'd avoid it if possible (but I say that without knowing anything about your errors or how many of them you're dealing with). The problem is that it only provides your users with a generic Win32 error message along the lines of "Access denied" or "File not found", which is unpleasant to .NET developers because it provides minimal context (i.e., what file wasn't found??).

To summarize, I'd translate as many of your error codes as possible to standard System exceptions, and, if you have additional useful information that might help callers' error handling then feed that info into the existing System exceptions (or create your own custom exception types if you must). Only throw Win32Exception as a last resort.

Mark Waterman
  • 961
  • 7
  • 16
  • Thanks for the answer. So it really seems there are no hidden caveats in going the second way. I've started implementing the interface using the second possibility and have no problems using it (though I'll still have to think about possible memory management problems when exceptions are thrown). – Martin Pecka Jan 20 '16 at 11:52