Tom Goff's .Net Musings

Tidbits of information regarding .Net, C#, and SQL Server.

Dependency Property Annoyance

leave a comment »

While I’m in the blogging mood, can you spot the bug with the code below?

public static readonly DependencyProperty MyCoolProperty = DependencyProperty.Register("MyCool",
    typeof(double),
    typeof(MyCoolObject),
    new FrameworkPropertyMetadata(0));

It’s not an obvious problem and unless you’re really into WPF it’s even less obvious. The problem is that when setting the default value of 0 (zero). The framework rightfully assumes it should be an int, but it will throw an exception when it tries to assign it to the associated dependency property during runtime. Why? Because it cannot implicitly convert the int type to a double type.To fix it you need to declare the dependency property like (notice the 0.0 in place of the 0):

public static readonly DependencyProperty MyCoolProperty = DependencyProperty.Register("MyCool",
    typeof(double),
    typeof(MyCoolObject),
    new FrameworkPropertyMetadata(0.0));

Written by Tom

April 4, 2008 at 11:53 am

Posted in .Net, C#, Gotcha, WPF

COTW: ConditionalAttribute Class

leave a comment »

The ConditionalAttribute class allows you to selectively include/exclude methods or classes based on a given condition. Before we show how to use the ConditionalAttribute class, we will describe conditions and how to define them.

A condition is simply a boolean flag with a given name. If a condition is defined, meaning it has been included or set, then it can be considered true. If it is not defined, then it can be considered false. Conditions can vary depending on the current configuration (e..g Debug, Release, etc) and the platform (e.g. Any CPU, x64, x86, etc). Based on these conditions, you can selectively include/exclude sections of code in your project.

These conditions are used by the compiler to include/exclude code from the final assembly. Since the conditions are used by the complier they must be defined at compile time and are not valid after the assembly has been built. There are two ways to define conditions in Visual Studio 2005. In addition, condition can be defined using the command-line build tools.

In Visual Studio 2005, there are two standard conditions: DEBUG and TRACE. By default, Debug builds define both of these conditions and Release builds only define the TRACE condition. In addition, you can define any number of additional conditions using the Project properties or in source code. The screen shot below shows the Project properties window where conditions can be defined:

ConditionalAttribute (Debug settings)

As you can see, the DEBUG and TRACE are defined by default and you can define your own custom conditions (MYCON1 and MYCON2). If we switch to the Release build, you can see that the conditions are different:

ConditionalAttribute (Release settings)

You can define conditions in source code using the #define directive. The example below shows how to define MYCON1 and MYCON2 in source code:

#define MYCON1
#define MYCON2

using System;
//...

The #define directives must be included before any other non-directive lines, such as the using statements. If you are coming from a C/C++ background then #define are nothing new, but there is one difference from the C/C++ counterpart. The #define in C# does not assign a value, it can only be used to define conditions. In C/C++, #define could be used to define conditions (a.k.a. symbols) and a value could also be associated with it.

NOTE: If you are using the command-line build tools, then you must define the DEBUG and TRACE conditions manually (unless you are building from the project).

Now that we know how to define conditions, let’s see how we can use them. There are two ways to check for conditions: #if directive and ConditionalAttribute. We will first look at the #if directive and it’s associated directives. Assume we have the following application:

using System;
using System.Diagnostics;

namespace ConditionalTestApp {
    class Program {
        static void Main(string[] args) {
            CheckLicense();
            // ... Run application ...
        }

        static void CheckLicense() {
            Console.WriteLine("Check License called");
            // ... Check license ...
        }
    }
}

In addition, assume we do not want to check the license if we are running a debug build (for whatever reason). Then we can use the #if directive to exclude the call to CheckLicense:

using System;
using System.Diagnostics;

namespace ConditionalTestApp {
    class Program {
        static void Main(string[] args) {
#if !DEBUG
            CheckLicense();
#endif
            // ... Run application ...
        }

        static void CheckLicense() {
            Console.WriteLine("Check License called");
            // ... Check license ...
        }
    }
}

This tells the compiler that the call to CheckLicense should not be included in the final assembly. Using Reflector, we can see that the call was excluded in the final debug assembly:

ConditionalAttribute (Reflector #if)

The #if directive requires a matching #endif directive to indicate the end of the block. In addition, you can use the #else and #elif directives to provide multiple paths or sections of code. Conditions can also be undefined using the #undef directive. The #if directive supports ! (not), && (and), || (or), and other boolean operations on the conditions. When using these directives, Visual Studio is smart enough to “gray out” any code that will not be included in the current build.

ConditionalAttribute (Visual Studio #if)

The ConditionalAttribute class is really just a simplified version of the #if directive. Anything that can be accomplished with ConditionalAttribute can be accomplished using the #if directive, with one minor exception that I will describe later. Using the #if directive to replace the ConditionalAttribute would take more work (in the form of typing), and would be harder to maintain.

The ConditionalAttribute class can only be used to check for the existence of a condition. It cannot be used to check if a condition is NOT defined, as we did in the example above using the #if directive. In order to modify our application to use the ConditionalAttribute instead of the #if directive, we need to define a new condition. We will call the condition CHECKLICENSE and we will define it only for the Release build. The new condition is defined in the Project properties and the updated source code is:

using System;
using System.Diagnostics;

namespace ConditionalTestApp {
    class Program {
        static void Main(string[] args) {
            CheckLicense();
            // ... Run application ...
        }

        [Conditional("CHECKLICENSE")]
        static void CheckLicense() {
            Console.WriteLine("Check License called");
            // ... Check license ...
        }
    }
}

Now if we look at the assembly in Reflector we will see that the call to CheckLicense has been removed from the debug build.ConditionalAttribute (Reflector attribute)

You can see that the ConditionalAttribute on the CheckLicense method is visible above as well. This is the one exception I alluded to earlier. This allows you to see, after the build, under what conditions the given method or class would be included or excluded.

With both our examples above, the CheckLicense method and it’s code are still included in the final assembly. Only calls to the given method where excluded. This may be a problem if you are trying to hide sensitive debug code from your users (e.g. how to bypass licensing). You could use the #if directive to exclude the code inside the CheckLicense method. This could be done in conjunction with using the ConditionalAttribute, to exclude the method calls.

Written by Tom

December 3, 2007 at 8:16 am

TOTW: Screen Capturing

leave a comment »

Maintaining a blog means I have to take screen shots every so often to illustrate a point. I have been using Jing, which is a free tool provided by TechSmith. In case you don’t know, TechSmith makes a commercial screen capture application called SnagIt. Recently, TechSmith decided to give away free licenses to older versions of SnagIt with the hopes you will upgrade. SnagIt has a lot of cool and very useful features. I’d highly recommend you check it out.

Another notable and free screen capture utility is Cropper (now on CodePlex), by Brian Scott.

Written by Tom

November 27, 2007 at 4:00 pm

Posted in Tip of the Week

The Catch with VS 2008 Multi-Targeting Support

leave a comment »

With the recent release of Visual Studio 2008, I have been trying to tinker with the new features when I have time. One of the features I especially like is the Multi-Targeting Support. You may have read about it before, but if not check out this blog. Using this feature, I could then benefit from the bug fixes, speed improvements, pretty interface changes, etc in Visual Studio 2008 with only minor changes to my applications. Unfortunately, there is a small catch.

If you read Scott Hanselman’s blog, then you may have read this entry. In order to install Visual Studio 2008, you obviously must install .Net 3.5 (which is all part of the Visual Studio setup). In order to install .Net 3.5, you must install .Net 3.0 SP1 and .Net 2.0 SP1. As Scott describes, there are new properties/methods that are added to the .Net 2.0 framework as part of SP1.

So if you develop an application that targets .Net 2.0 in Visual Studio 2008 and use one of the new methods or properties, then obviously your application will not run on a computer with .Net 2.0 RTM. Since the assembly versions from the RTM and SP1 are the same, your application will load the RTM assemblies and then throw an exception when it can’t find the required method or property. If you do not use any of the new properties or methods, then your application will run on a computer with .Net 2.0 RTM. In addition, you could simply apply the .Net 2.0 SP1 to the target computers.

There are a few ways to determine if a property, method, or class is new. The first is obviously the documentation. For example, the INotifyPropertyChanging interface is new to .Net 2.0 SP1 and you can see that .Net 2.0 is not included in the “Version Information” section at the bottom. The second option is to use a new optional FxCop rule (as described here) to flag items. Finally, you can test your assemblies on a computer with .Net 2.0 RTM. This last step really requires that you perform full test coverage of your assembly though.

Written by Tom

November 27, 2007 at 3:33 pm

Posted in .Net, C#, Gotcha, Visual Studio

COTW: DebuggerNonUserCodeAttribute Class

leave a comment »

The DebuggerNonUserCodeAttribute class allows you to specify classes, structs, constructors, properties, and methods that are not considered “user code”. Using this attribute is the same as applying both DebuggerHiddenAttribute and DebuggerStepThroughAttribute, with one notable exception.

In my previous blog entry about the DebuggerHiddenAttribute, I said

In the tool-tip above, Visual Studio implies that if ‘Just My Code’ was disabled then we would be able to step into class members that have the DebuggerHiddenAttribute. Although, in my tests this was not the case. With ‘Just My Code’ disabled, Visual Studio shows the break point as enabled, but it is never hit and I cannot step into the “hidden” method.

I was referring to the following image, which implies that I should be able to debug items marked with the DebuggerHiddenAttribute:

DebuggerHiddenAttribute 2

I found that if ‘Just My Code’ is disabled, then Visual Studio does ignore DebuggerNonUserCodeAttribute (but not DebuggerHiddenAttribute). Therefore, it’s probably better to use the DebuggerNonUserCodeAttribute in most cases, since it can be disabled by the user.

Written by Tom

November 27, 2007 at 12:29 pm

COTW: DebuggerStepThroughAttribute Class

leave a comment »

The DebuggerStepThroughAttribute[^] class allows you to specify classes, structs, constructors, properties, and methods that you do not want the debugger to step into. Unlike DebuggerHiddenAttribute[^], which we saw last week[^], you can still set break points in items that have DebuggerStepThroughAttribute specified and Visual Studio will not disable them.

This gives you the benefit of automatically stepping over items, while still allowing you to debug the item if needed. If we change our example from last week to use the DebuggerStepThroughAttribute, then we can set a break point in the GetFormat method if we suspect it has a defect.

using System;
using System.Diagnostics;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            PrintMessage(GetFormat(), "Hello World");
        }

        [DebuggerStepThrough]
        static String GetFormat() {
            return "MyApp: {0}";
        }

        static void PrintMessage(String format,
            params Object[] args) {
            Console.WriteLine(format, args);
        }
    }
}

For properties, this attribute can only be applied to the get and set blocks, as shown below:

// DebuggerStepThrough cannot be applied here
public Boolean MyProperty {
    [DebuggerStepThrough]
    get {
        return true;
    }
    [DebuggerStepThrough]
    set {
        // Set something
    }
}

Attributes like DebuggerStepThroughAttribute are only recommendations to the debugger and the debugger is not required to follow them. If you are using Visual Studio, then it’s a safe bet that the debugger will respect them. With that in mind, these attributes can make your debugging life easier.

Written by Tom

November 5, 2007 at 7:32 am

TOTW: Avoid Unnecessary EventArgs Allocations

leave a comment »

In a previous blog entry about the generic EventHandler delegate, I included an example similar to the following example:

public class MyObject {
    // ... Other code ...

    /// <summary>
    /// This event is fired when something happens.
    /// </summary>
    [field: NonSerialized]
    public event EventHandler<MyCustomEventArgs> SomeEvent;

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The event arguments.</param>
    private void OnSomeEvent(Object sender,
        MyCustomEventArgs e) {
        if (null != SomeEvent)
            SomeEvent(sender, e);
    }
}

public class MyCustomEventArgs : EventArgs {
    /// <summary>
    /// Initializes a new instance of the
    /// <see cref="MyCustomEventArgs"/> class.
    /// </summary>
    /// <param name="whatHappened">What happened.</param>
    public MyCustomEventArgs(String whatHappened) {
        this.whatHappened = whatHappened;
    }

    /// <summary>
    /// Holds a string that tells what happened.
    /// </summary>
    private String whatHappened;

    /// <summary>
    /// Gets a string that tells what happened.
    /// </summary>
    /// <value>What happened.</value>
    public String WhatHappened {
        get {
            return this.whatHappened;
        }
    }
}

In general, most developers would include additional overloads of the OnSomeEvent method to make their lives easier. For example, the following overload of OnSomeEvent allows you simply provide the “what happened” text and the method handles everything else.

/// <summary>
/// This method is used to fire the <see cref="E:SomeEvent"/>
/// event.
/// </summary>
/// <param name="whatHappened">What happened.</param>
private void OnSomeEvent(String whatHappened) {
    OnSomeEvent(this, new MyCustomEventArgs(whatHappened));
}

The problem with the code above is that a new instance of MyCustomEventArgs is allocated even if SomeEvent is null. Eventhough, nobody is subscribing to the SomeEvent event, we are performing a memory allocation.

We can update our overload so that the memory allocation is only performed if someone is actually subscribing to the event.

/// <summary>
/// This method is used to fire the <see cref="E:SomeEvent"/>
/// event.
/// </summary>
/// <param name="whatHappened">What happened.</param>
private void OnSomeEvent(String whatHappened) {
    if (null != SomeEvent)
        SomeEvent(this, new MyCustomEventArgs(whatHappened));
}

Now, the allocation of MyCustomEventArgs is only performed if it’s needed. If this event is fired often and typically does not have any handlers hooked up, then we can remove any unneeded burdon on memory and the garbage collector. 

With the example above, the OnSomeEvent methods are private. If you are expecting your class to be extended, then you may want to make OnSomeEvent(Object, MyCustomEventArgs) protected/public and virtual. This allows derived classes to customize the behavior of the SomeEvent event. If we change OnSomeEvent(String) so that it calls the event directly (instead of calling OnSomeEvent(Object, MyCustomEventArgs)), then dervied classes would have to override this overload as well. If OnSomeEvent needs to be virtual, then it’s probably best not to make the change described here.

Written by Tom

November 1, 2007 at 7:49 am

Follow

Get every new post delivered to your Inbox.