C# preprocessor #if check for #nullable enable directive - c#

New versions of C# have a directive to allow object types to be assumed as non-null by default. I have a unity library that's in use by older and newer projects, and I want to support both of them but also still take advantage of the nice nullability feature for newer versions. I tried basically using an #if directive that checks for a particular unity version to determine which level of nullability to implement:
#if UNITY_2021_3_OR_NEWER
#nullable enable
#endif
// define some stuff
#if UNITY_2021_3_OR_NEWER
#nullable restore
#endif
However, it seems that even when an #if directive evaluates to false, the older C# compilers still read #nullable enable and recognize that it's an invalid directive (for that compiler's version). Is there any way to make this work with older versions, maybe through some version check I'm unaware of or something else?

Related

Can you add a preprocessor directive for a C# version?

Is there a way to add a preprocessor directive that compares the C# version used by the compiler?
For example :
public T MyMethod<T>()
{
#if CS_7
return default; // Feature 'default literal' is not available in C# 7.0. Please use 7.1 or greater.
#else
return null; // Ignore the fact that this won't work, it isn't the point of the question
#endif
}
Would the .NET version be the way to go here? Wouldn't there be situations where the compiler used is different for the same project? (i.e. if different employess use different versions of Visual Studio)
Apparently you can't, but the C# version used depends on the framework version (list of version per framework) used in the project, which provides a default C# version, unless configured otherwise manually through something like the property (see linked documentation).
Thus, most situations where you would want a C# version preprocessor directive can either be resolved by adding a framework preprocessor directive or forcing a specific C# version in the project itself using the property in the project file.

Is there a way I can have Resharper ignore an unused reference?

Using Resharper, we can right click on References for a project and select Optimize References. This shows us class libraries that are not in use or required by the compiler.
I have a class library that is only to be used as a reference (won't ever be a need to actually use the code). The dll is setup to inject itself upon start up as long as it is part of the references. In case you are curious why this would ever be done, it handles not found and errors for ASP.NET MVC projects (Nuget package page).
Is there any possible way that I can tell Resharper that this reference is either part of the required by the compiler or a part of the used references? I just want to try and prevent developers from removing my dll on accident.
You can interface Resharper with StyleCop. It allow warning in your code based on StyleCop settings.
For each warning there is a way (using the "Resharper bubble") to disable a warning :
http://tof.canardpc.com/view/49d10973-eb25-4a26-90b2-19d872083285.jpg
it's add a comment line in your code to disable alert on the warning ;
// ReSharper disable once RedundantUsingDirective
using My.Unused.Reference;
After some tests, saldy it seems Resharper doesn't care about that when you trigger the "Optimize Reference"

how to install and use Code Contracts?

I have a basic question, might be it is so obvious but for some reason i can't seem to be successful with installing and using Code Contracts.
I've downloaded the package from MSDN, installed it following the online documentation but i still get an IDE warning for the below code statement:
Contract.Requires(inputParameter != "");
the IDE warning is:
"Method invocation is skipped. Compiler will not generate method invocation because the method is conditional, or it is partial method without implementation"
Anything I'm missing in the process of enabling Code Contracts? I'm using VS2010 Ultimate SP1
Most likely this is due to Code Contracts not being configured in the project settings. If you go to your project properties, you should see a Code Contracts tab. On the tab, select the mode you are building in (Debug|Release|Both) and then turn on Code Contracts features by checking the appropriate check boxes.
I've seen the warning that you detail when Code Contracts are not set to Build.
If you don't see the Code Contracts tab, then you might need to install Code Contracts on your machine. Do this by downloading and installing the installer from here.
Conditional compilation is all driven from compiler preprocessor definitions. This is the same approach used for the DEBUG constant, although Visual Studio hides the definition of that behind a checkbox. It's an efficient approach because when those symbols aren't defined then the methods aren't called at all; importantly the parameters being passed aren't evaluated either, so you can use relatively expensive checks in your code contracts without worrying about those checks slowing down release builds.
Microsoft's introduction to Code Contracts says this:
Most methods in the contract class are conditionally compiled; that is, the compiler emits calls to these methods only when you define a special symbol, CONTRACTS_FULL, by using the #define directive. CONTRACTS_FULL lets you write contracts in your code without using #ifdef directives; you can produce different builds, some with contracts, and some without.
Although this talks about using #define in the code to turn on code contracts:
#define CONTRACTS_FULL
as #NirMH said in the comments it's usually better to define it in the conditional compilation symbols for the project so you can have it on for some builds and off for others.
Note that CONTRACTS_FULL is the only option you have, although it's clearly been named to allow the possibility of more granular control in future.

Check using preprocessor if app is a winforms or asp.net

Is this possible to check in assembly what client (winforms app or asp.net page) is running it?
I want to add some methods but only for specific client.
I know, there is predefined DEBUG (#if DEBUG). Where can I find full list, what can I check using preprocessor?
To expand on m0sa's answer, preprocessor directives are basically just a string passed to the compiler.
If you are so inclined, you can add new build configurations (example: instead of Debug/AnyCPU and Release/AnyCPU, you could make WebDebug/AnyCPU, WinformsDebug/AnyCPU, WebRelease/AnyCPU, etc).
Then in the properties page of your project, for each configuration you could provide a value in the 'Conditional compilation symbols' field. For example, for WebDebug and WebRelease, you could provide the conditional symbol WEB. Then, you would be able to use:
#if WEB
using MyNamespace.WebStuff;
#endif
You will need multiple build configurations for that and define different a preprocessor directive for each one. You can set the conditional preprocessor directives in the Build tab of the project Properties page.There are no other directives defined, just the DEBUG directive which you can turn on and off (together with the TRACE directive) in the same tab. Note that DEBUG it is not defined for the "release" build configuration. This is kind of what you will need to do to enable different versions of the assembly to be built.
References:
MSDN
www.davidarno.org <-- see this one for a more visual description

How does C# compile the code with #if preprocessor directive?

I wonder how to compiler compile my code if I using #if directive inside my code.
I would like to create special version of my application (commercial demo version) and I want to limit the functionality of my application. I would rather avoid the obfuscation and just don't want to add all my compiled code to executable file. I need solution resists preview my code during disassembly process. Can I use #if directives for variant compilation instead making comments for disabling code parts?
Using the #if directive is like using the preprocessor in c++, in that the code would simply not be present if the condition hasn't been met (in compilation time). From MSDN:
When the C# compiler encounters an #if
directive, followed eventually by an
#endif directive, it will compile the code between the directives only if
the specified symbol is defined.
Unlike C and C++, you cannot assign a
numeric value to a symbol; the #if
statement in C# is Boolean and only
tests whether the symbol has been
defined or not.
As an addition to #ohadsc's answer: you can always check with Reflector what is actually produced by the compiler.

Categories