In Solution properties, I have Configuration set to "release" for my one and only project.
At the beginning of the main routine, I have this code, and it is showing "Mode=Debug".
I also have these two lines at the very top:
#define DEBUG
#define RELEASE
Am I testing the right variable?
#if (DEBUG)
Console.WriteLine("Mode=Debug");
#elif (RELEASE)
Console.WriteLine("Mode=Release");
#endif
My goal is to set different defaults for variables based on debug vs release mode.
DEBUG/_DEBUG should be defined in VS already.
Remove the #define DEBUG in your code. Set preprocessors in the build configuration for that specific build.
The reason it prints "Mode=Debug" is because of your #define and then skips the elif.
The right way to check is:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Don't check for RELEASE.
By default, Visual Studio defines DEBUG if project is compiled in Debug mode and doesn't define it if it's in Release mode. RELEASE is not defined in Release mode by default. Use something like this:
#if DEBUG
// debug stuff goes here
#else
// release stuff goes here
#endif
If you want to do something only in release mode:
#if !DEBUG
// release...
#endif
Also, it's worth pointing out that you can use [Conditional("DEBUG")] attribute on methods that return void to have them only executed if a certain symbol is defined. The compiler would remove all calls to those methods if the symbol is not defined:
[Conditional("DEBUG")]
void PrintLog() {
Console.WriteLine("Debug info");
}
void Test() {
PrintLog();
}
I prefer checking it like this over looking for #define directives:
if (System.Diagnostics.Debugger.IsAttached)
{
//...
}
else
{
//...
}
With the caveat that of course you could compile and deploy something in debug mode but still not have the debugger attached.
I'm not a huge fan of the #if stuff, especially if you spread it all around your code base as it will give you problems where Debug builds pass but Release builds fail if you're not careful.
So here's what I have come up with (inspired by #ifdef in C#):
public interface IDebuggingService
{
bool RunningInDebugMode();
}
public class DebuggingService : IDebuggingService
{
private bool debugging;
public bool RunningInDebugMode()
{
//#if DEBUG
//return true;
//#else
//return false;
//#endif
WellAreWe();
return debugging;
}
[Conditional("DEBUG")]
private void WellAreWe()
{
debugging = true;
}
}
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='
The method Debug.Assert has conditional attribute DEBUG. If it is not defined, the call and the assignment isDebug = true are eliminated:
If the symbol is defined, the call is included; otherwise, the call (including evaluation of the parameters of the call) is omitted.
If DEBUG is defined, isDebug is set to true (and passed to Debug.Assert , which does nothing in that case).
If you are trying to use the variable defined for the build type you should remove the two lines ...
#define DEBUG
#define RELEASE
... these will cause the #if (DEBUG) to always be true.
Also there isn't a default Conditional compilation symbol for RELEASE. If you want to define one go to the project properties, click on the Build tab and then add RELEASE to the Conditional compilation symbols text box under the General heading.
The other option would be to do this...
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
Be sure to define the DEBUG constant in the Project Build Properties. This will enable the #if DEBUG. I don't see a pre-defined RELEASE constant, so that could imply that anything Not in a DEBUG block is RELEASE mode.
Remove your defines at the top
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
NameSpace
using System.Resources;
using System.Diagnostics;
Method
private static bool IsDebug()
{
object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
if ((customAttributes != null) && (customAttributes.Length == 1))
{
DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
}
return false;
}
Slightly modified (bastardized?) version of the answer by Tod Thomson as a static function rather than a separate class (I wanted to be able to call it in a WebForm viewbinding from a viewutils class I already had included).
public static bool isDebugging() {
bool debugging = false;
WellAreWe(ref debugging);
return debugging;
}
[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
debugging = true;
}
A tip that may save you a lot of time - don't forget that even if you choose debug under the build configuration (on vs2012/13 menu it's under BUILD => CONFIGURATION MANAGER) - that's not enough.
You need to pay attention to the PUBLISH Configuration, as such:
It is worth noting here that one of the most significant differences between conditionally executing code based on #if DEBUG versus if(System.Diagnostics.Debugger.IsAttached) is that the compiler directive changes the code that is compiled. That is, if you have two different statements in an #if DEBUG/#else/#endif conditional block, only one of them will appear in the compiled code. This is an important distinction because it allows you do do things such as conditionally compile method definitions to be public void mymethod() versus internal void mymethod() depending on build type so that you can, for example, run unit tests on debug builds that will not break access control on production builds, or conditionally compile helper functions in debug builds that will not appear in the final code if they would violate security in some way should they escape into the wild. The IsAttached property, on the other hand, does not affect the compiled code. Both sets of code are in all of the builds - the IsAttached condition will only affect what is executed. This by itself can present a security issue.
I got to thinking about a better way. It dawned on me that #if blocks are effectively comments in other configurations (assuming DEBUG or RELEASE; but true with any symbol)
public class Mytest
{
public DateTime DateAndTimeOfTransaction;
}
public void ProcessCommand(Mytest Command)
{
CheckMyCommandPreconditions(Command);
// do more stuff with Command...
}
[Conditional("DEBUG")]
private static void CheckMyCommandPreconditions(Mytest Command)
{
if (Command.DateAndTimeOfTransaction > DateTime.Now)
throw new InvalidOperationException("DateTime expected to be in the past");
}
Remove the definitions and check if the conditional is on debug mode. You do not need to check if the directive is on release mode.
Something like this:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
Since the purpose of these COMPILER directives are to tell the compiler NOT to include code, debug code,beta code, or perhaps code that is needed by all of your end users, except say those the advertising department, i.e. #Define AdDept you want to be able include or remove them based on your needs. Without having to change your source code if for example a non AdDept merges into the AdDept. Then all that needs to be done is to include the #AdDept directive in the compiler options properties page of an existing version of the program and do a compile and wa la! the merged program's code springs alive!.
You might also want to use a declarative for a new process that is not ready for prime time or that can not be active in the code until it's time to release it.
Anyhow, that's the way I do it.
Is there any way with a preprocessor to execute code according to the version of C#?
Example:
#if CSharpVersion = 7.3
var value = 1;
#endif
One option would be to define the LangVersion explicitly in the Project file and have the constants defined based on it. For example,
<LangVersion>7.3</LangVersion>
and
<DefineConstants Condition="'$(LangVersion)' == '7.3'">DEBUG;TRACE;LANG_VERSION_7_3</DefineConstants>
<DefineConstants Condition="'$(LangVersion)' != '7.3'">DEBUG;TRACE;LANG_VERSION_NOT_7_3</DefineConstants>
Now you could use directives as
#if LANG_VERSION_7_3
Console.WriteLine("C# 7_3");
#elif LANG_VERSION_NOT_7_3
Console.WriteLine("Not C# 7_3");
#endif
Please note the LANG_VERSION would signify the compiler accepts syntax specified version or lower.
I'm writing a class that I wish to use on both Windows & Linux.
One of the methods that is in this class is accessing the Windows Registry
What I'm hoping to achieve is to somehow disable this particular method from being used when using a Linux machine.First of all I did some research to see if there was something for .Net Core that would allow me to check which operating system is in use, I found this and sure enough that works.When I implemented it into my code when accessing a method, I was hoping to disable the method that's accessing the windows registry, however the closest I could get to this was using a switch statement, something like this
switch (OS)
{
case OSX:
return;
case LINUX:
return
}
To return if the operating system was not supported, this worked, however I then thought disabling it from being accessed all together would be much better rather than throwing an error for an operating system thats not supported for that particular methodI then went on to look at preprocessor directives thinking that if I'm able to detect and disable parts of code depending the frameworks etc, maybe I could use something like this to disable parts of code depending on the operating system that way they could never be called even when trying to access the methodI went on from there to see if I could disable parts of code using preprocessor directives.I found this.I understand that it is for C++ however it seems to be the closest I could find for what I'm trying to achieve within .Net Core In a perfect world, it would look something like this
/// <summary>
/// Get the file mime type
/// </summary>
/// <param name="filePathLocation">file path location</param>
/// <returns></returns>
`#if WINDOWS`
public static string GetMimeType(this string filePathLocation)
{
if (filePathLocation.IsValidFilePath())
{
string mimeType = "application/unknown";
string ext = Path.GetExtension(filePathLocation).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
{
mimeType = regKey.GetValue("Content Type").ToString();
}
return mimeType;
}
return null;
}
`#endif`
I did see #Define so I tried something like this #define IS_WINDOWS and added it to my class along with #if IS_WINDOWS
however, I couldn't see how to change that value if I'm hoping to just reuse the static class over and over.
While you could pursue a route involving #define, it's compile-time and you'll loose a lot of .Net's multi-platform goodness. You'll also have to juggle multiple configurations, multiple builds, etc.
Where possible, hide the platform-dependent behavior behind a platform-independent abstraction and do the check at runtime using System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform:
interface IPlatform
{
void DoSomething();
}
class WindowsImpl : IPlatform
{
public void DoSomething()
{
// Do something on Windows
}
}
class LinuxImpl : IPlatform
{
public void DoSomething()
{
// Do something on Linux
}
}
// Somewhere else
var platform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new WindowsImpl() : new LinuxImpl();
platform.DoSomething();
This works well for many things including PInvoke. You will be able to use the same binaries on either platform, and it will be easier to add OSX later.
If you need to isolate the platform-dependent code at compile-time (perhaps a package is Windows-only), MEF2/System.Composition can help you make a plugin framework where each platform gets its own assembly:
// In Windows.dll class library project
using System.Composition;
[Export(typeof(IPlatform))]
public class WindowsImpl : IPlatform
{
public void DoSomething()
{
//...
}
}
And then in your main program:
using System.Composition.Hosting;
var configuration = new ContainerConfiguration();
var asm = Assembly.LoadFrom(pathToWindowsDll);
configuration.WithAssembly(asm);
var host = configuration.CreateContainer();
var platform = host.GetExports<IPlatform>().FirstOrDefault();
I have a use-case where preprocessor directives are necessary. I found here that I can do this. As the site tells us, add the following to your project (.csproj) file:
<PropertyGroup>
<TargetFramework>...</TargetFramework>
<OutputType>...</OutputType>
<!-- insert the following -->
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
... then add these for each preprocessor option:
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
It is the individual <PropertyGroup Condition> child element that defines the constant so I can do this:
#if Linux
private const string GLFW_LIB = "glfw";
#elif OSX
private const string GLFW_LIB = "libglfw.3";
#elif Windows
private const string GLFW_LIB = "glfw3";
#else
// some error condition - unsupported platform
#endif
I need to get a value from configuration manager in C# Preprocessor directive
And want to do as like below,
#if System.Configuration.ConfigurationManager.AppSettings["Language"].Equals("en-US");
{
bool languageCheck=TRUE
}
#endif
Is it possible ?
No, pre-processors mean "pre-compilation", and at that point it does not know what values are stored in objects or configurations. However, you can add a different build configuration (by clicking on project properties going to build tab), and add the language flag to it to do a similar thing.
public void SayLanguage()
{
#if en_US
Console.WriteLine("en_US");
#else
Console.WriteLine("Language not defined.");
#endif
}
This question already has answers here:
How do you use #define?
(8 answers)
Closed 8 years ago.
They have to be placed on the top of your .cs file. You cant create those guys dynamically at runtime and you cant give them a value or change their value because there is no value at all so whats the point of #define keyword?
Here is an example:
#define DEBUG
#define MYTEST
using System;
public class MyClass
{
static void Main()
{
#if (DEBUG && !MYTEST)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && MYTEST)
Console.WriteLine("MYTEST is defined");
#elif (DEBUG && MYTEST)
Console.WriteLine("DEBUG and MYTEST are defined");
#else
Console.WriteLine("DEBUG and MYTEST are not defined");
#endif
}
}
Both are defined on top so why having all those ifs anyway?
Can somebody tell me scenarios where define is usefull?
Sorry if this is a duplicate just let me know in comments if so and I ll remove this question.
The point is condiional compialtion.
Like:
#ifdef x64
....
#else
....
#endif
#ifdef KIOSK
fullScreen =true;
#else
fullScreen =false;
#endif
You create condition for compile time, so your binaries will not change at runtime, but
will fit exact requirements of your target ambient you are compiling for.It could be whatever you want, it's up to you decide name and semantics of what you #define.
EDIT.
Example: you have a program that acess low level windows API, and you have to support
x86 and x64 versions. In this case you may want that in binaries (so after compilation) of your program for 32bit, there is no any evidence of 64bit functions. So you may write
#ifdef x64 //conditional compilation symbol defined by YOU
DriverInfo GetDriverInfo64(..) {...} //64bit
#else
DriverInfo GetDriverInfo(..) {...} //32bit
#endif
You don't need to define these symbols with #define, you can set them globally in the project settings or per compiler argument. But sometimes it comes in handy when you can alter the value of a symbol (set/unset) for a single file, for testing or debugging purposes. Then #define will be your friend :)
You should remove the two #define statement at the top. If you use Visual Studio to compile, you can then have the option to turn the debug on or not. If you turn on debug, the compiler will know what section to have in your code and which to leave out.
Suppose you have DEBUG turned on, your code will look like:
using System;
public class MyClass
{
static void Main()
{
Console.WriteLine("DEBUG is defined");
}
}