Conditional compilation can make your code hard to understand and maintain. Personally, I am against it.
My suggestion is that you utilize good design patterns to isolate the platform specific bits,
http://codebetter.com/patricksmacchia/2011/11/07/real-world-feedback-on-a-net-to-mono-migration/
JavaDepend is a Windows Forms project, so its porting experience may help you.
WinForms executable (.exe) -> Platform adapter (.dll) -> Windows (.Windows.dll)
|
--> Other platforms (.Unix.dll)
In this way, you can always compile the whole solution together, package them together. At runtime, the adapter can load correct platform assembly/assemblies after platform detection.
For you case maybe you can use WPF for Windows, then you have to isolate WPF bits from business logic code, and then write UI again for other platforms (GTK# for Linux, MonoMac for OS X). This approach can be visualized as
WinForms/WPF executable (.exe) -> Platform independent biz-logic code (.dll)
^ ^
MonoMac executable ---| |
|
GTK\# executable ------|
In this way, you need to package differently for each platforms, but the core assembly/assemblies can be the same.