“One of the huge benefits of the preprocessor in C/C++ was conditional compilation. It's great than C# included it. It's bizarre to me that Java hasn't.”
The C preprocessor can make it way to easy to break code, for example when it is used for feature flags and/or multi-platform support. If you have N feature flags, you have to compile 2^N different programs. Multiply by M for supporting M platforms.
It also makes it impossible to check whether source code can be compiled. The text inside a
#ifdef FOO
...
#endif
block doesn’t have to be valid source code, but the compiler cannot know whether it has to be.
I think that’s why Java ditched it, and I think that makes sense. Adding a more limited feature, like C# did, makes sense, too, though. I’m not sure C#’s variant is limited enough, though. it still is subject to that 2^N problem, but gets saved from its main problems because C# isn’t running on as diverse environments as where lots of C code evolved.
That’s true, but it is done a lot cleaner than in the wild west days of the C preprocessor, where feature-specific, compiler-specific, and platform-specific #ifdef’s were sprinkled throughout the source code seemingly without much thought (but keeping things working must have taken lots of thought), nested #ifdef’s were common, and often not all cases had separate paths in the code.
Dependency injection can be made messy, too, but that takes more of an effort. You can also test injected code in isolation. That may take some effort, but those preprocessor messes only could be tested as part of the entire product.
As I said, I can see why they wanted to get rid of that. Not adding a same replacement may not have been the best choice, but I am not sure of that. Programming culture also had to change, and that sometimes requires drastic action. Apple also did that in the Mac by not providing any text mode (forces programmers to make windowed applications) and by removing cursor keys from the first keyboard (forces programmers to provide a good mouse interface)
The C preprocessor can make it way to easy to break code, for example when it is used for feature flags and/or multi-platform support. If you have N feature flags, you have to compile 2^N different programs. Multiply by M for supporting M platforms.
It also makes it impossible to check whether source code can be compiled. The text inside a
block doesn’t have to be valid source code, but the compiler cannot know whether it has to be. I think that’s why Java ditched it, and I think that makes sense. Adding a more limited feature, like C# did, makes sense, too, though. I’m not sure C#’s variant is limited enough, though. it still is subject to that 2^N problem, but gets saved from its main problems because C# isn’t running on as diverse environments as where lots of C code evolved.