Archives

Time for another look at “pure .NET”

Back in the Nineties there was a lot of fuss about “pure Java”. This meant Java code without any native code invocations that tie the application to a specific operating system.

It is possible to write cross-platform Java code that invokes native code, but it adds to the complexity. If it is an operating system API you need conditional code so that the write API is called on each platform. If it is a custom library it will have to be compiled separately for each platform.

Over on the Microsoft .NET site, developers have tended to have a more casual approach. After all, in the great majority of cases the code would only ever run on Windows. Further, Microsoft tended to steer developers towards Windows-only dependencies like SQL Server. After all, that is the value of owning a developer platform.

Times change. Microsoft has got the cross-platform bug, with its business strategy based on attracting businesses to its cloud properties (Office 365 and Azure) rather than Windows. The .NET Framework has been forked to create .NET Core, which runs on Mac and Linux as well as Windows. SQL Server is coming to Linux.

Another issue is porting applications from 32-bit to 64-bit, as I was reminded recently when migrating some ASP.NET applications to a new site. If your .NET code avoids P/Invoke (Platform Invoke) then you can compile for “Any CPU” and 64-bit will just work. If you used P-invoke and want to support both 32-bit and 64-bit it requires more care. IntPtr, used frequently in P/Invoke calls, is a different size. If you have custom native libraries, you need to compile them separately for each platform. The lazy solution is always to run as 32-bit but that is a shame.

What this means is that P/Invoke should only be used as a last resort. Arguably this has always been true, but the reasons are stronger today.

This is also an issue for libraries and components intended for general use, whether open source or commercial. It is early days for .NET Core support, but any native code dependencies will be a problem.

Breaking the P/Invoke habit will not be easy but “Pure .NET” is the way to go whenever possible.

Related posts:

  1. Nokia Lumia strategy needs time, may not have it
  2. ASP.NET Padding Oracle fix released, time to patch for Windows administrators
  3. Time to stop using non-generic collections
  4. More RSS madness from Microsoft – this time it’s Live Mail
  5. Measuring start-up time for .NET, Java, C++

3 comments to Time for another look at “pure .NET”

  • I don’t think this is prudent advice. It even has some completely wrong or partially wrong statements in it:

    > If your .NET code avoids P/Invoke (Platform Invoke) then you can compile for “Any CPU” and 64-bit will just work

    Not true. You can still compile your .NET library for AnyCPU and call native code. Yes you do need to versions of the native library, but you can pick the right one dynamically.

    > IntPtr, used frequently in P/Invoke calls, is a different size.

    I’m not sure what you’re trying to say here. That’s the beauty of it. It changes size to match the architecture, so you don’t have to do a thing. This is a good thing!

    > If you have custom native libraries, you need to compile them separately for each platform

    And there’s no problem with that. Build servers do that for you, or you pick a dropdown and build again. You often don’t update your C++ libraries as often as your managed main project, so really isn’t an issue. Add to this that .NET Native also compiles to the platform and architecture, so you’re not really saving anything there.

    > If it is an operating system API you need conditional code so that the write API is called on each platform.

    Naturally you wouldn’t call a system API on a different system. The reason for doing that would be to light-up extra functionality on the specific platform. Again this is a good thing, and something only relying on .NET core doesn’t give you.

    Personally I think cross-platform code is WAY more important than cross-platform binaries.

    > What this means is that P/Invoke should only be used as a last resort. Arguably this has always been true, but the reasons are stronger today.

    I think this is the worst advice you can give, and based on all faulty arguments or “being lazy” reasons. This is the worst kind of purist .NET supremacy, telling people to avoid C/C++ for the sake of avoiding C/C++. C++ has lots and lots of benefits. Despite .NET becoming more crossplatform, it’s on no where near as many platforms as C++. There’s more powerful C++ heavy processing libraries you can pull in than .NET.

    If you really want to follow this advice (please don’t), promise me that you’ll never use Sqlite again.

  • tim

    Hi Morten and thanks for your comment.

    1. I didn’t say that P/Invoke won’t work if you compile for “Any CPU”. The point is that it might or might not work across different CPU bitness if you use P/Invoke. If you don’t use P/Invoke it is very likely to work seamlessly.

    2. IntPtr changing size automatically is a good thing but the fact that ints are a different size is a common source of porting issues.

    I have a lot of experience of P/Invoke, not least thanks to a project called HTMLEditor which wraps MSHTML for use from C#. 32-bit to 64-bit is not always straightforward. See this article for more details:

    https://msdn.microsoft.com/en-us/library/ms973190.aspx#64mig_topic4

    and note issues like different field offsets; these are not automatically fixed.

    3. It is all very well “lighting up” extra functionality on specific platforms but having cross-platform code just work is also a benefit. Of course if you are writing UI code then native functionality is more important, while with library code there is usually less need; performance can be an issue of course.

    4. There is nothing in my piece about avoiding C/C++. I am talking about .NET code. But there is a question: should you have your .NET Code dependent on P/Invoke to native binaries? Clearly there are times when you need to do this, but it is worth avoiding unless you have to. There was actually a promising port of SQLite to C# though I am not sure what happened to it; that was when Silverlight was a thing (some of the same factors applied).
    and note

  • Interesting perspective. I now lead an open source project, the Chemistry Add-In for Word. This is written in C#, but uses VSTO to integrate directly with Word. We’re also looking now at expanding the scope of the project to provide molecular structure display and editing. These new components will be written using Windows Presentation Foundation.

    So, I suppose I don’t see an easy way to extricate myself from Microsoft’s clutches. But I’m not in a hurry to do so because not word processor out there has the sheer extensibility of Word, and WPF is going to make my job as a chemoinformatics developer very much easier. Even if the latter has been eclipsed by other technologies, such as JavaScript on the Windows Runtime, which offer dubious benefits.