views:

83

answers:

3

In the following console application example, the event is defined like this:

public delegate void PurchaseHandler(object obj, PurchaseArgs args);
public event PurchaseHandler OnPurchaseMade;

It seems to me after reading around that this might be a bit "C#2".

Is there a more abbreviated way to express this with C#3 and C#4?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestEvents288202
{
    class Program
    {
        static void Main(string[] args)
        {
            Product product1 = Product.LoadProduct(222);
            EmailManager.NotifyAdministrator(product1);
            product1.OnPurchaseMade += new Product.PurchaseHandler(NotifyUser);
            product1.Purchase();

            Product product2 = Product.LoadProduct(333);
            EmailManager.NotifyAdministrator(product2);
            product2.OnPurchaseMade += new Product.PurchaseHandler(NotifyUser);
            product2.Purchase();

            Console.ReadLine();
        }

        static void NotifyUser(object sender, PurchaseArgs e)
        {
            ((Product)sender).Log();
            Console.WriteLine(e.Message);
        }
    }

    public static class EmailManager
    {
        public static void NotifyAdministrator(Product product)
        {
            product.OnPurchaseMade += new Product.PurchaseHandler(SendEmail);
        }

        public static void SendEmail(object sender, PurchaseArgs e)
        {
            Product product = sender as Product;
            Console.WriteLine("Just sent e-mail to administrator notifying of purchase of article {0}", product.ProductNumber);
        }
    }

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

        public PurchaseArgs(string message)
        {
            Message = message;
        }
    }

    public class Product
    {
        public int ProductNumber { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

        public delegate void PurchaseHandler(object obj, PurchaseArgs args);
        public event PurchaseHandler OnPurchaseMade;

        public static Product LoadProduct(int productNumber)
        {
            List<Product> products = new List<Product>();
            products.Add(new Product { ProductNumber = 111, Name = "Intel CPU", Description = "Newest model, very fast." });
            products.Add(new Product { ProductNumber = 222, Name = "Philips Monitor", Description = "22-inch, very nice." });
            products.Add(new Product { ProductNumber = 333, Name = "Sony Camera", Description = "10 Megapixels, sharp pictures." });

            return products.Where(p => p.ProductNumber == productNumber).SingleOrDefault();
        }

        public void Purchase()
        {
            PurchaseArgs purchaseArgs = new PurchaseArgs(String.Format("The product \"{0}\" was just purchased.", this.Name));
            OnPurchaseMade(this, purchaseArgs);
        }

        public void Log()
        {
            Console.WriteLine("Log: #{0} purchased.", this.ProductNumber);
        }
    }
}
+9  A: 

Always define events like this, don’t use custom delegates:

event EventHandler<EventArgsClassType> MyEventHandler;

or, if they don’t take arguments:

event EventHandler MyEventHandler;

By being based on the System.EventHandler class, this ensures a uniform signature for all events, following the .NET guidelines.

If your event takes further arguments, its EventArgsClassType must inherit from System.EventArgs.


Furthermore, when instantiating an event handler, you don’t have to use this explicit form:

product1.OnPurchaseMade += new Product.PurchaseHandler(NotifyUser);

since method groups can be implicitly converted to matching delegates. As a consequence, the following code works just as well:

product1.OnPurchaseMade += NotifyUser;
Konrad Rudolph
the second part of your answer was my next question, it works with that change, thanks
Edward Tanguay
+1  A: 

At first, you could use the EventHandler template to create the delegate, so your code would be:

public event EventHandler<PurchaseArgs> OnPurchaseMade;
Bruno Brant
+3  A: 

Try this:

public event EventHandler<PurchaseArgs> OnPurchaseMade;

Also, lines like this:

product1.OnPurchaseMade += new Product.PurchaseHandler(NotifyUser);

Can be simplified:

product1.OnPurchaseMade += NotifyUser;
Dan Puzey