May 20, 2010

C++ Virtual Destructor

Look at this Why are destructors not virtual by default? Basic rule is if a class has at least one virtual function, it should have a virtual destructor
Example:
class Base 
{
...
  virtual ~Base();
...
};

class Derived : public Base 
{
 ...
  ~Derived();
};

C++ auto_ptr and shared_ptr

std::auto_ptr

Good article on why and how to use it Another good article on when and how to use it
{
  auto_ptr<T> ptr( new T );
  ...
} // when ptr goes out of scope it deletes the underlying object!
  • auto_ptr employs the "exclusive ownership" model. This means that you can't bind more than one auto_ptr object to the same resource.
  • Be careful when passing as a parameter to a method by value because on returning the pointer will point to nothing. The copy in the method will destroy the pointer when the method ends, so pass it by reference.
  • Also because of this do not use it with template libraries!

std::tr1::shared_ptr

  • Unlike auto_ptr, shared_ptr uses reference counting so multiple "shared_ptr"s can point to the same resource.
  • Destructor decrement the reference count. When it reaches zero the resource is "delete"d.
  • Can have a user defined deleter, so shared_ptr need not necessarily hold a "pointer to something" type resource, it could be a file handle, etc. Define a "delete" function to delete the custom resource
  • Be careful of cyclic references, the objects will not be able to delete one another

May 14, 2010

Example Using std::map<> In C++

See Wikipedia reference
std::map<XXX*, DataAveragerPtr> averagerCache;
const XXX* xxx = ...

DataAveragerPtr averager;
if(averagerCache.find(xxx) == averagerCache.end())
{ // Not found so create a new one
  averager.reset(new SomeDataAverager(...));     
  averager->DoSomethingExpensive();
  averagerCache.insert (std::pair<XXX*, DataAveragerPtr>(
  xxx, averager));
}
else // found it
{
  // for parametric types <A, B> use an A to get a B,
  // B b = mymap[a]; where a is of type A
  averager = averagerCache[xxx]; // lookup
}
...
if (!averagerCache.empty())
averagerCache.clear();
When passing it as a parameter, the best option is to pass it by reference and just create it on the stack.

Events In C#

Look here: How to: Implement Events in Your Class - A good beginners guide.
and here: C# events vs. delegates - Good detailed explanation of events and how they differ from delegates

Implementing the event in Your Publisher Class

Step 1 (Optional): Define your custom "EventArgs" class
public class SomethingChangedEventArgs : EventArgs
{
...
}
The following steps take place in the event publisher class
class SomethingChangedEventPublisher
{
Step 2: Expose your custom EventHandler
  public event EventHandler<SomethingChangedEventArgs> SomethingChanged; // for events with custom arguments
  public event EventHandler SomethingChanged; // otherwise use this for standard events
Step 3: Define an event publishing helper method (this is agood practice)
  void PublishSomethingChangedEvent(SomethingChangedEventArgs ea)
  {
    EventHandler<SomethingChangedEventArgs> eh = this.SomethingChanged
    if (eh != null)
      eh(this, ea);
  }
Step 4: Publish/Fire/Trigger the event in the appropriate places
  ...
  PublishSomethingChangedEvent(this, new SomethingChangedEventArgs(...));
  
  ...
}

Subscribing to the event in the Listener/Observer/Subscriber Class

The following steps take place in the event observer/subscriber class
class SomethingChangedEventSubscriber
{
Step 5: Subscribe to the event
  // VS Intellisense will do most of the work for you here!
  SomethingChangedEventSource.SomethingChanged += new EventHandler<SomethingChangedEventArgs>(OnSomethingChanged);
...
Step 6: Handle the event
  // The method where the SomethingChangedEvent is processed 
  private void OnSomethingChanged(object sender, SomethingChangedEventArgs eargs)
  {
    // SomethingChanged detected, now do something with it here
  }
...
Step 7: Unsubscribe to the event. This is in my experience the biggest cause of memory leaks in C# programs
  // VS Intellisense will do most of the work for you here!
  SomethingChangedEventSource.SomethingChanged -= new EventHandler<SomethingChangedEventArgs>(OnSomethingChanged);
  
...
}
Alternatively, use an inline delegate to handle the event
SomethingChangedEventSource.SomethingChanged += delegate (object sender, SomethingChangedEventArgs e)
{
  ...
};
But there is a danger to doing this see here
Also in Windows Forms programs events often lead to memory leaks as the events were never detached seehere
Note that the event source is called the "Event Publisher", ie. it is the class containg the event definition. The event target or "Subscriber" is the object attaching a delegate to the event. Be careful with C# events and the Garbage Collection of unreferenced objects. A C# event publisher holds a reference to the subscriber so the Subscriber cannot be disposed of until that event is detached (or there is no longer a reference to either the publisher or subscriber). This also means that if the subscriber has a Dispose event, you cannot rely on the system to invoke it in a GC round until that event is detached. If you attach a subscriber on to the event of a publisher, ensure it is detached

May 12, 2010

Creating A Single Instance WPF Application

Look here: Initial idea. - Did not seem to work!
How can I provide my own Main() method in my WPF application?
and here

Simplest solution found:
  1. On App.xaml build properties, set "Build Action" to Page.
  2. Add following code to "App.xml.cs" or equivalent, the "App" class source.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;

...

[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static void Main()
{
  // Use mutex to ensure only single instance is running
  bool mutexOwnershipGranted = true;
  using (Mutex mutex = new Mutex(
    true, 
    "$SOMEUNIQUESTRING$", // Use GUID or string id here
    out mutexOwnershipGranted))
  {
    // If this is the only running instance
    if (mutexOwnershipGranted) 
    { // Then run app 
      DevHelperWpf.App app = new DevHelperWpf.App();
      app.InitializeComponent();
      app.Run();
    }
    else 
    { // Bring current running instance to the front
      Process current = Process.GetCurrentProcess();
      foreach (Process process in Process.GetProcessesByName(
          current.ProcessName))
      {
         if (process.Id != current.Id)
         {
            SetForegroundWindow(process.MainWindowHandle);
            break;
         }
      }
    }
  }
}

March 24, 2010

Environment Variables

Environment.SetEnvironmentVariable Method on MSDN provides some comprehensive samples

Use of "Environment.GetEnvironmentVariables()" Example:
...
  ShowEnvironmentVariables(EnvironmentVariableTarget.User);
  ShowEnvironmentVariables(EnvironmentVariableTarget.Machine);
  ShowEnvironmentVariables(EnvironmentVariableTarget.Process);
...
private static void ShowEnvironmentVariables(EnvironmentVariableTarget targ)
{
    IDictionary ret = Environment.GetEnvironmentVariables(targ);
    string[] keys = new string[ret.Count];
    string[] values = new string[ret.Count];
    ret.Keys.CopyTo(keys, 0);
    ret.Values.CopyTo(values, 0);

    string targStr = targ.ToString().ToUpper();
    string underlineStr = "=======";
    Debug.WriteLine(targStr);
    Debug.WriteLine(underlineStr);
    for (int ix = 0; ix < ret.Count; ix++)
    {
        Console.WriteLine(keys[ix] + " = " + values[ix]);
    }
    Debug.WriteLine("");
}
To write an Environment variable use "Environment.SetEnvironmentVariable"
// by default the environment variable is set on the "Process"
Environment.SetEnvironmentVariable("TestEnvVar", "change1");
// but can be set for the user
Environment.SetEnvironmentVariable("TestEnvVar", "andagain", EnvironmentVariableTarget.User);
// or the system (if the program is executed through an account 
// with the appropriate permissions)
Environment.SetEnvironmentVariable("TestEnvVar", "andagain", EnvironmentVariableTarget.Machine);

February 16, 2010

ZipStorer

Quick way to include Zip file functionality.
Find up to date version at http://zipstorer.codeplex.com/
The nice thing about ZipStorer is that you dont need to reference any other assemblies, you just include the class file in your project and away you go.
Quick and dirty example of using ZipStorer to compress a bunch of files:
...
saveFilePath = System.IO.Path.ChangeExtension(saveFilePath, "zip");
StringBuilder fileList = new StringBuilder();
string comment = "File changes from: " + 
                 DateTime.UtcNow.ToLongDateString() +
                 Environment.NewLine +
                 "Original path: " + rootDir;                                  
using (ZipStorer zipStore = ZipStorer.Create(saveFilePath, comment))
{
    foreach (CheckedListItem cli in listBoxFilesChanged.SelectedItems)
    {
        if (cli.FileSystemInfo.Exists)
        {
            zipStore.AddFile(ZipStorer.Compression.Deflate, // Compress
               cli.FullName,     // Full path of file to be added
               cli.RelativeName, // Stored as a relative path in zip file
               cli.FullName);    // Comment for stored file (source of the original)
            fileList.AppendLine(cli.FullName);
        }
    }
}
...