There are couple of places where #if seems to give you abilities that polymorphism doesn’t:
- Conditionally specifying base class
- When a section contains code that is not recognised by a compiler on another platform
- e.g. some new operator only supported on one platform
I was thinking about splitting into 3 partial classes so each platform includes the 2 it requires, but that seems worse to me.
Example 1
Changing base class, depending on condition
public class FullBase
{
public void Register()
{
Console.Write("I am full featured so will use the :-) operator");
int a = 1 :-) 2
}
}
public class MobileBase
{
public void Register()
{
Console.Write("My compiler does not know what the :-) operator is");
}
}
#if MOBILE
public class MyClass : MobileBase
#else
public class MyClass : FullBase
#endif
{
//...
}
Example 2
Here, I have a class to hide the IDisposable pattern boilerplate. If I moved to DI, I think it would introduce DI boilerplate in the many derived classes.
public class Disposable : IDisposable
{
//...
private void RunChecks()
{
#if !MOBILE
//Use reflection to walk the OBJECT tree looking for potential issues
#endif
}
}
public class A: Disposable
{
//...
protected override void DisposeManagedResources()
{
}
}
// Also Class B, C, D, E.....
2
Conditional compilation effectively creates multiple versions of the code base. That’s exactly the purpose of version control branches.
The other alternative is put whatever code needs to vary in its own assembly/dll
. Different dll
s can contain different implementations of the same class (assuming the public fields are the same).
Both alternatives have the advantage of not cluttering the code with every alternate implementation simultaneously and presenting only the code you’re working with as a coherent whole.
2