The C# language specification is almost identical across the majority of runtimes. But writing 100% portable C# code is a little bit more restricting than you think. Following are the general C# coding rules that were observed during the Nevron Open Vision (NOV) development. We call C# files that obey them NOV C# files. All of the C# files that constitute the main NOV product line (i.e. that produce runtime specific dlls for the core and extension libraries) are NOV C# files. Hosts do not obey to such rules, since they need not be portable.
1. No Third Party DLLs and Namespaces except System
The main thing that makes C# unportable is the third party libraries that your project references. And by third party we mean all non NOV libraries. C# code consumes such dependencies when you create object instances or call methods of types declared in such libraries. The 100% portable C# file should not have such dependencies in order to be compiled on any environment. As a general rule of thumb all NOV C# files begin with a usings block that only references NOV namespaces. The only allowed non NOV namespace is the System namespace that has some essential types, which are bound to the CLR. Note that even though NOV C# code may need to reference this namespace, this does not mean that it is dependent on the specific DLL that implements this namespace under a specific environment. This is because types such Type and Exception are implemented on all .NET CLR runtimes - they are just packed in a different DLL.
2. Limited Use of the types in the System namespace
Even though most of the types are present on most CLR runtimes, you cannot count on that. That is why code that requires to use such types needs to be compiled on each targeted runtime. NOV C# files have a limited use of the System namespace, that is tested to run on all supported runtimes. For example: there is no NOV type that implements IDisposable or ICloneable, since these interfaces are not part of the Silverlight runtime. As a consequence we do not use the using statement in NOV. As another consequence we do not implement interfaces declared in specific .NET frameworks in general.
3. No Use of Language statements that bind to Framework Types
.NET tempts you to write code that binds too many C# language statements to CLR types. NOV does not use such statements. Specifically we do not use the foreach statement (also for performance reasons), LINQ and many others. In general we stick to simple language statements and constructs.