views:

44

answers:

3

When I comment out the fm.OnLoaded line below, it gives me an error that OnLoaded is null.

How can I make it optional for the caller of my class to consume the event or not as with .NET classes / events?

using System;
using System.Windows;

namespace TestEventLoaded8282
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            FileManager fm = new FileManager();
            //fm.OnLoaded += new FileManager.LoadedHandler(fm_OnLoaded);
            fm.Load();
        }

        void fm_OnLoaded(object obj, FileManagerArgs args)
        {
            Console.WriteLine("the file manager is loaded: " + args.Message); 
        }
    }

    public class FileManager
    {
        public string Name { get; set; }

        public delegate void LoadedHandler(object obj, FileManagerArgs args);
        public event LoadedHandler OnLoaded;

        public FileManager()
        {}

        public void Load()
        {
            Name = "this is the test file manager";
            OnLoaded(this, new FileManagerArgs("no errors"));
        }
    }

    public class FileManagerArgs : EventArgs
    {
        public string Message { get; set; }

        public FileManagerArgs(string message)
        {
            Message = message;
        }
    }
}
+3  A: 

Check for null before invoking the delegate. The following is a common pattern:

public event EventHandler<FileManagerEventArgs> Loaded;

public void Load()
{
    ...
    OnLoaded(new FileManagerEventArgs("no errors"));
}

protected virtual void OnLoaded(FileManagerEventArgs e)
{
    EventHandler<FileManagerEventArgs> handler = this.Loaded;
    if (handler != null)
    {
        handler(this, e);
    }
}
dtb
+1 This is the typical way to write event handlers, at least from what I've seen. I like having the separate OnLoaded method in case there needs to be additional logic before/after an event handler is fired.
Kevin Babcock
+1 thanks, I'll use this as well later
Edward Tanguay
+3  A: 
if (OnLoaded != null) {
    OnLoaded(this, new FileManagerArgs("no errors"));
}
Webleeuw
that's what needed to get it to work thanks
Edward Tanguay
+3  A: 

You need to check that the OnLoaded event handler is not null before invoking it:

LoadedHandler handler = OnLoaded;

if (handler != null)
{
    handler(this, new FileManagerArgs("no errors"));
}

You will need to do this every time you invoke an event handler. The local handler variable above is to catch the case where you can check that the handler is non-null, but something removes the handler before you call it. Creating a local variable captures the handler to prevent this.

An alternative approach is to define the event handler as:

public event LoadedHandler OnLoaded = delegate{};

This declares a default empty event handler, making the null check redundant (there is a slight performance loss using this approach though).

adrianbanks
+1 for the delegate{} tip, works.
Edward Tanguay