I am looking to write some C# code for linux/windows/mac/any other platform, and am looking for best practices for portable code.

Project mono has some great porting resources.

What are the best practices for portable C#?

+4  A: 

Don't use Windows.Forms for GUIs, but Mono probably mentioned that already. Gtk# is much more consistent and reliable for cross platform GUIs.

+1  A: 

If you want the code to be portable, you need to closely review the list of completed features on the Mono site. They go into detail on each class in the framework, and the level of completeness. You will have to take these things into consideration during the design process so that you don't go too far down a path and discover that a critical feature has not yet been implemented.

Eric Z Beard
+8  A: 

I've actually used winforms and it was fine. It was BUTT UGLY, but it worked.

Obviously, don't use P/Invoke, or any win32 stuff like the registry. Also be aware of any third party DLL's. For example, we use a third party SQLite dll which actually contains native code in it which we have to swap out if we want to run on OSX/linux.

Orion Edwards
Gendarme and MoMA can help as well.
+10  A: 

I hate the term "Best practice" because it seems that some practices can be the best in any context, which is a risky thing, but I'll tell what I consider a "Good practice" for multi-platform code (and for most other type of development):

Use a continuous integration engine and build for all the target platforms all the time.

Sounds too complex? Well, if you really need to support multiple platforms, better to do it. No matter how careful you are with your code and library usage, if you test too late, you'll find yourself spending looong hours reworking big portions of the app.

Best luck!

Martin Salias
+3  A: 

A few years ago I would have advised you to buy yourself a copy of my book on cross-platform .NET, but as the book's somewhat out-of-date now you really need to stick to the info of the Mono site.

The Mono Migration Analyzer (MoMA) tool is pretty good for analyzing an exsisting .NET application and warning you of portability problems, but the best bet for new code is to use the latest stable version of Mono for your development work.

As Orion said you need to be careful when using 3rd party DLLs, although my co-author wrote a NativeProbe tool to analyze DLLs for P/Invoke dependenecies if you do want to quickly check 3rd party software.

If you are determined to develop on MS .NET then you should try and ensure you also build and unit test on Mono, and you should also watch out for a number of Windows specific namespaces such as the Microsoft.Win32 and System.Management namespaces.

+1  A: 

There are some other simple things. Like don't assume path characters. Or newlines.

I'm one of the people who regularly compiles NUnit on Mono on Linux or OSX.

Also, don't assume that the compilers work exactly the same. We've found an issue recently where the MS C# compiler appears to be including things that the Mono one doesn't, requiring extra references in our build script.

Other than that, it has been pretty straightforward. I remember the first time we got the GUI running on Mono/Linux - it was pretty exciting (even if it was pretty ugly)

Cory Foy
+7  A: 

Watch out for anything to do with filename and path manipulation and make use of the portable .NET methods in System.IO.Path ie.

instead of:

string myfile = somepath + "\\file.txt";


string myfile = Path.Combine(somepath, "file.txt");

If you need to specify a path separator then you would use Path.Separator etc

Sam Warwick
+7  A: 

Don't use "\r\n" for a new line. Use Environment.NewLine

Remember :

  • *NIX uses just the newline character ("\n")
  • Windows uses "\r\n"
  • MacIntosh uses "\r" (I am not really sure about this - feel free to correct me).

L.E.: It seems that some newer MacOSes don't use the "\r" line separator anymore.

Andrei Rinea
Macintosh USED to use \r. These days it uses \n, thanks to the BSD base. Not sure exactly when it changed. It could still be an issue though.
Matthew Scharley
:) Thx for the info, monoxide.
Andrei Rinea

One missing item: Make sure that file names are case sensitive. File.Open ("MyFile.txt"); isn't going to work on Unix if your file is named myfile.txt.