简体   繁体   中英

Removing preprocessor branching in C#

I am refactoring some source code and got a task to remove preprocessor compiling. I have now searched internet for some days, but haven't found any good idea how to do that. I am also quite new to C#.

So the problem is following, I have different interfaces (classes) for every device and "ControlLogic" class needs to use only one of them at the time. Device is chosen on program run-time. So far "device" variable (also used globally) is used in a lot of places and considering renaming that doesn't make sense to me. Also all device interfaces (classes) are derived from base class, but interface classes does implement different methods for them.

public class ControlLogic
{
#if FIRST_DEVICE
        public FirstDeviceInterace device = null;
#elif SECOND_DEVICE
        public SecondDeviceInterface device = null;
#elif THIRD_DEVICE
        public ThirdDeviceInterface device = null;
#endif

// One example method
public void startDevice()
{
    if (device != null)
    {
#if (FIRST_DEVICE || SECOND_DEVICE)
         device.startDevice();
#endif

#if THIRD_DEVICE
         device.startThirdDevice();
#endif
     }
}

// More code.....
}

So what is the best way to remove preprocessor compiling?

I've faced with a similar task a few months ago: large C# code base and extensive preprocessor directives usage. Manual refactoring looked like a long boring monkey job there. I've failed with unifdef , sunifdef and coan C tools because of C# syntax specifics like #region and some others. In the long run I've made my own tool undefine . It uses regexp to parse the preprocessor directives and sympy python library to simplify logical expression. It works good for me on large 10M lines code base.

I understand that the three device types do not have a common base class or interface. You cannot just pick one of the three at runtime and type all variables with a base type.

Here are a few options:

  1. Find a way to aa common base type .
  2. If you cannot modify the classes (or it would be inappropriate for some reason) write a wrapper . That wrapper can have any structure you like. You could have one wrapper per device class with a common base type.
  3. Use dynamic . This can be a quick fix at the cost of less tooling help (less autocompletion, less documentation at hand, less quick static error checking).

Using #if to solve this problem is very unusual. It is problematic because the amount of testing to even make sure the code compiles has now tripled. You also need multiple binaries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM