Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Tuesday, December 3, 2013

Adding Code Just for Debug Build with C#

It's very easy to add code that will only run for Debug builds for C# projects. The if directive is all you really need to know to do this.

Just add the following two lines to your source file:

#if DEBUG
#endif

You put the code that you want for the Debug build between those two lines. When you compile the project using the 'Debug' build configuration, the compiler will include the code between those two lines. Otherwise, they are ignored.

What if you want to include code for anything other than the Debug build? Just swap 'if DEBUG' for 'if !DEBUG' in the first line of code.

Troubleshooting

The reason why this works is that, by default, the Debug build configuration of a C# project defines the 'DEBUG' constant. If your debug-only code doesn't run when using a debug build, the problem might be in your build settings.

In Visual Studio:
  • Right-click the project that you're working on
  • Click 'Properties'
  • Click on the 'Build' tab
  • Make sure that the build configuration is set to Debug (using the dropdown menu that should be at the top of the build settings pane)
  • Make sure that 'Define DEBUG constant' is checked 
  • Save (Ctrl + S)

Making Your Own Special Build

Because this behavior only relies on C#'s #if directive and a preset DEBUG constant, you can easily use this to add code for any special build of your project. A good example of this is a 'Demo' build configuration. If you setup a Demo configuration for your commercial application, you can sprinkle #if directives statements throughout your code and get demo-specific (or retail-specific) functionality in your program.

The following how-to was written using Visual Studio 2013, but I think that it will work just fine if you're using VS 2008 or later.

1. Add Solution Build Configuration

This can be done through the Build > Configuration Manager... window. Click the 'Active solution configuration' then click '<New...>'. Give it a name like 'Demo'. You should probably copy settings from the Release build. Make sure that 'Create new project configurations' is unchecked unless you want to add one for each project. Click OK, but don't close the 'Configuration Manager' window.

2. Add Project Build Configuration

Look at the 'Project contexts' grid/spreadsheet. Click on the 'Configuration' cell for your project. Click '<New...>'. Give it the same name as your solution config, copy the Release build settings, and uncheck 'Create new solution configurations'. Click OK, but don't close the 'Configuration Manager' window.

3. Use the new project build configuration

Make sure that the 'Active solution configuration' is your new config (Demo).  Click on the 'Configuration' cell for your project and select your new project config. Close Configuration Manager.


4. Add the conditional compilation symbol

  • Right-click the project that you're working on
  • Click 'Properties'
  • Click on the 'Build' tab
  • Make sure that the build configuration is set to your new config (using the dropdown menu that should be at the top of the build settings pane) 
  • Type your new compilation symbol in the 'Conditional compilation symbols' text box
  • Save (Ctrl + S)
 

5. Use your new compilation symbol in code

If you're using 'DEMO' as the compilation symbol, sprinkle these two lines throughout your code to write build-specific code.

#if DEMO
#endif

Sunday, May 19, 2013

.NET Debugging Tips

In my three years of professional coding experience, I have fixed many problems in .NET programs and unit tests. One example of this is a WPF problem that ultimately involved a faulty GetHashCode() implementation. Most of the problems that I have faced involve NullReferenceExceptions, off-by-one errors, bad regular expressions, and "normal" stuff like that. I've fixed some major concurrency-related issues and even a bug that took 13 steps to re-produce. I don't have a decade of experience, but I know a thing or two about debugging .NET code.

(I) Don't Rely on Breakpoints

Visual Studio has excellent support for breakpoints, but I rarely use them. Removing a breakpoint can be a time-consuming process if you want to leave other breakpoints enabled. They also stop the program entirely, and I've seen cases where breakpoints prevent concurrency issues from being re-produced.

I use breakpoints only when I need to look at local variables in a buggy piece of code. Otherwise, I just sprinkle Debug.WriteLine statements when needed. I can act on Debug info faster than I can a breakpoint, and the program doesn't stop for seconds while printing debug statements.

There is one major disadvantage to using Debug.WriteLine: you have to alter source code to use it. Please do not commit code with Debug statements that you don't plan to keep. Every version control system that I know of has a diff support, and you should check these diffs when you commit code.

(I) Have Plenty of Unit & Integration Tests

I am a big proponent of unit & integration testing. I feel that good tests help developers figure out what isn't causing a problem before they start. Automated testing is not the end-all, be-all of bug prevention. You'll miss edge cases, and there's no way (that I know of) to detect weird GUI-related issues before you stumble upon them. Tests are merely good tools.

If you are able to, I highly recommend writing integration tests. In past endeavors, I had to mock everything out to such an extent that real-world issues (like a missing table, column, or bad parameters) would not be detected until the manual testing phase. My software uses SQLite, and I write tests that write data to real SQLite database. These integration tests helped me write persistence code that didn't easily break.

While debugging, I try to write unit & integration tests that cover the bug. This helps me debug the problem and ensures that the exact same problem does not return in future code revisions.

Rules of Thumb

Common NullReferenceException causes

When my code throws a  NullReferenceException, it's usually one of two things:
  1. I forgot to check a parameter or property for null
  2. Type cast returns null (and I forgot to check for null)

Silently handling exceptions is bad

Silently handling exceptions silence major problems with your code. It also makes your code harder to debug. I highly recommend not writing error-handling code that does nothing.

Of course, I've written error-handling code that basically does nothing. The hack was very well documented to indicate why I was silently handling exceptions, and I didn't catch Exception. That's bad because StackOverflowException and OutOfMemoryException exist.
 
On a related note, catching an exception and throwing a new one can hide the true source of the exception.

 It's probably your regular expression

If a regular expression can be the cause of a problem, it probably is! This isn't a knock against regular expressions, as they can be very useful for validating certain types of input. It's just tough to write one that works all of the time for all cases.

Saturday, May 11, 2013

Freezing jQuery NuGet Package Version

jQuery v2.0.0 was released last month, and it does not support Internet Explorer 6/7/8. If you use NuGet to include jQuery in your .NET projects, your jQuery files might be updated to this latest version without old IE compatibility. You can force NuGet to keep v1.9.1 when you update your solution's packages, but you have to manually edit the package file for each project with jQuery.

A project's packages.config file can be found in the root directory of that project (where the .proj file is). Open each packages.config file and look for a line similar to this one:


<package id="jQuery"
            version="1.9.1" 
            targetFramework="net40" />

(The targetFramework attribute may be different)

Adding an allowedVersions attribute allows you to control what version will be used by NuGet during updates. Here's an example:

<package id="jQuery"
            version="1.9.1"
            allowedVersions="[1,2)"
            targetFramework="net40" />
allowedVersions="[1,2)" tells NuGet to grab the newest version that falls between v1.0 and v2.0 (excluding v2). This will likely be v1.9.1, the most current version before v2.0.0.

For more information on NuGet versioning, please go to NuGet versioning documentation.