Mittwoch, 3. Juni 2015

Reducing repetition in native wrappers using expression bodied members

Whenever wrapping legacy or native APIs in .NET i hate the verbosity of the code that needs to be written. APIs without a concept of exceptions are often designed returning error codes which requires results to be passed back per reference. In .NET this translates to using out-Parameters.
Here is an example taken from NAudios wrapper for the Windows Core Audio API, see here.:
public string ID
{
  get
  {
    string result;
    Marshal.ThrowExceptionForHR(deviceInterface.GetId(out result));
    return result;
  }
}
This usage pattern repeats all over the code base. Using the helper method Marshal.ThrowExceptionForHR already helps reducing lines but it is still not a one liner.

Wouldn't it be nice to use C# 6 Expression Bodied Members here? Of course, but the out-Parameter signature prevents the obvious refactoring path of reducing the code block to a one-liner using lambdas/delegates.

It seems many folks still believe that lambdas cannot be with out- and ref-Parameters because lambdas cannot directly capture out and refs. Actually, this is quite simple to do. Here is what i came up with
public string Id => MarshalEx.Get(deviceInterface.GetId);
using
static class MarshalEx
{
  public delegate int FuncOut(out T value);

  public static T Get(FuncOut getter)
  {
    T result;
    Marshal.ThrowExceptionForHR(getter(out result));
    return result;
  }
}
Pretty sweet: 9 lines reduced to a one-liner. Overall, this reduced the number of lines down to to 40% of its original size at the same time improving readability. So, less space for you bugs to hide!

Keine Kommentare:

Kommentar veröffentlichen