Tom Goff's .Net Musings

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

Archive for the ‘Tip of the Week’ Category

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.

Advertisements

Written by Tom

November 27, 2007 at 4:00 pm

Posted in Tip of the Week

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

TOTW: EventArgs.Empty

leave a comment »

Events in .Net should always have two parameters: sender and the event arguments. The first parameter is the object that generated the event. The second parameter is either an instance of EventArgs[^] or a class derived from EventArgs.

By using a class derived from EventArgs, developers can include additional information about the event. The following code, shows a typical event definition:

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>
    protected virtual void OnSomeEvent(Object sender,
        MyCustomEventArgs e) {
        if (null != SomeEvent)
            SomeEvent(sender, e);
    }
}

In the event above, I specify that the event will use MyCustomEventArgs (not shown). I can then include additional properties in MyCustomEventArgs as needed. There are times when no additional information can be or needs to be included with the event. In these cases, the event typically takes an instance of EventArgs. An example of this is shown here:

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

    /// <summary>
    /// This event is fired when something happens.
    /// </summary>
    [field: NonSerialized]
    public event EventHandler<EventArgs> 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>
    protected virtual void OnSomeEvent(Object sender,
        EventArgs e) {
        if (null != SomeEvent)
            SomeEvent(sender, e);
    }
}

The following code shows an example of how to fire this event. In addition, it shows an overload of OnSomeEvent that provides the appropriate parameters.

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

    /// <summary>
    /// This method is used to do something important.
    /// </summary>
    public void SomeMethod() {
        // ... Other code ...

        OnSomeEvent(this, new EventArgs());

        // ... Other code ...
    }

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    protected virtual void OnSomeEvent() {
        if (null != SomeEvent)
            SomeEvent(this, new EventArgs());
    }
}

The code above works great, but has one problem. Every time SomeEvent is fired, we allocate a new instance of EventArgs. Since EventArgs is immutable and has no properties or fields, we could allocate a single global instance of EventArgs and use that single instance every time we fire our event. Luckily, .Net already defines such an instance in EventArgs.Empty[^].

Using this new global instance of EventArgs, our code would look like this:

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

    /// <summary>
    /// This method is used to do something important.
    /// </summary>
    public void SomeMethod() {
        // ... Other code ...

        OnSomeEvent(this, EventArgs.Empty);

        // ... Other code ...
    }

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    protected virtual void OnSomeEvent() {
        if (null != SomeEvent)
            SomeEvent(this, EventArgs.Empty);
    }
}

I put together a small sample project[^] to demonstrate the additional allocation. I also included a test of the Empty field from the String class. This is the code from the sample project:

static void Main(string[] args) {
List strings = new List(10000);
List eventArgs = new List(10000);
Int64 before, after;

Console.Write(“Starting \”\” test…”);
strings.Clear();
before = GC.GetTotalMemory(true);
for (Int32 i = 0; i < 10000; i++) strings.Add(""); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.Write("Starting String.Empty test..."); strings.Clear(); before = GC.GetTotalMemory(true); for (Int32 i = 0; i < 10000; i++) strings.Add(String.Empty); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.Write("Starting new EventArgs() test..."); eventArgs.Clear(); before = GC.GetTotalMemory(true); for (Int32 i = 0; i < 10000; i++) eventArgs.Add(new EventArgs()); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.Write("Starting EventArgs.Empty test..."); eventArgs.Clear(); before = GC.GetTotalMemory(true); for (Int32 i = 0; i < 10000; i++) eventArgs.Add(EventArgs.Empty); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.ReadKey(); }[/sourcecode]Note: I realize GC.GetTotalMemory isn’t the most accurate way to detect memory allocations.

And this is the output from one test run:

emptyfieldtest

As you can see, the only time the total memory is increased is when we create new instances of EventArgs (as expected). Strings have special handling in .Net, such as string interning[^], but there is no special handling for EventArgs. This means you have to specifically use the EventArgs.Empty field.

You won’t see a huge improvement, if any, by using EventArgs.Empty. This is just a good coding practice.

Written by Tom

October 23, 2007 at 8:02 am

TOTW: Google ‘site’ keyword

leave a comment »

While not specifically related to the topics covered by my blog, I do find the following to be invaluable. When searching for information on a given .Net class (or whatever), sometimes the results are cluttered with irrelevant links. To reduce the clutter, I will often use the “site” keyword in my Google searches.

For example, if we search Google for DebuggerDisplayAttribute[^] then we get a little over 1000 hits. We can specify our search expression as “DebuggerDisplayAttribute site:wordpress.com” to limit the results from the wordpress.com site as shown here[^].

 Google has many[^] more search criteria that you can specify, all of which can help you find what you need. Most other search engines will have similar options, but I tend to use Google.

Written by Tom

October 16, 2007 at 8:33 am

Posted in Tip of the Week

TOTW: Visual Studio’s Shortcuts

leave a comment »

Visual Studio has a lot of functionality, some of which is mostly unknown. It’s hard to present all the functionality Visual Studio has to offer without overwhelming the user. Therefore, most commands are not visible through the menu or toolbars. However, there are many more commands tied to keyboard short-cuts.

We are all familiar with keyboard short-cuts which use a single key along with a combination of the Control, Alt, and/or Shift keys. Some examples of these types of short-cuts include Ctrl+C for copy, Ctrl+X for cut, etc. Visual Studio 2005 introduced key chords, which are multiple keys typed while holding down the Control key. For example, if you select some code then press and hold the Control key and type K+C, then the selected code will be commented out. These key chords allow a single key, such as C, to be used for various commands. In addition, the first key of the chord can be used to group similiar commands. For example, Ctrl+K+U will uncomment the selected text.

I’d recommend learning the short-cuts for commands you use frequently. If a command you use alot does not already have a short-cut, then I’d recommend assigning one. Microsoft as alot of information on this subject, but I’ve included some links to get you started:

Written by Tom

October 7, 2007 at 10:12 pm

TOTW: Snippet Complier

with one comment

Often times I need to test or verify a small piece of C# code. Instead of creating a full-blown Visual Studio solution, I usually turn to Jeff Key’s Snippet Compiler[^]. This handy little tool allows you to write and test “snippets” of C#, VB.Net, and JScript.Net code. Best of all, I don’t have dozens of unneeded solutions sitting around on my hard disk.

Written by Tom

September 30, 2007 at 7:27 pm

Posted in .Net, C#, Tip of the Week