By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,991 Members | 1,380 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,991 IT Pros & Developers. It's quick & easy.

Easier way to extend behavior?

P: n/a
I want to create a class which is like a List<T>, except that whenever
a T is added, it raises an event.

Simple concept, I think, but I can't seem to find a simple execution.

Ideally I would inherit from List<T> and override an OnAdd method:

// This doesn't work
public class NotifyingList<T> : List<T>
{
public delegate void ItemAddedHandler(T item);
public event ItemAddedHandler ItemAdded;

void OnAdd(T item)
{
base.OnAdd(item);
ItemAdded(item);
}
}

But there isn't such an OnAdd method.

I could inherit from List<T> and *shadow* the Add(T) method, casting
down to the base class to do the actual adding and then raising the
event:

public class NotifyingList<T> : List<T>
{
public delegate void ItemAddedHandler(T item);
public event ItemAddedHandler ItemAdded;

new public void Add(T item)
{
((List<T>)this).Add(item);
ItemAdded(item);
}
}
But Shadowing Is Bad, and also any client of the class could:

static void Main(string[] args)
{
NotifyingList<String> foo = new NotifyingList<string>();
foo.ItemAdded += StringAdded;

foo.Add("apple");
foo.Add("banana");

// evil client!
((List<string>)foo).Add("pear");

Console.ReadLine();
}

static void StringAdded(string s)
{
Console.WriteLine(s);
}
Neatly sidestepping the event raising mechanism just by downcasting (or
is it upcasting).

I could keep a private List<T> myself, and make my public signature the
same as that of a List<T>, writing code to delegate every operation to
my private List<T>, with the addition of the event raising:

public class NotifyingList<T>
{
public delegate void ItemAddedHandler(T item);
public event ItemAddedHandler ItemAdded;

private List<T> items;

public void Add(T item)
{
items.Add(item);
ItemAdded(item);
}

public ReadOnlyCollection<T> AsReadOnly()
{
return items.AsReadOnly();
}

public int BinarySearch(T item)
{
return items.BinarySearch(item);
}

public void foo()
{
items.foo();
}

// etc
// etc
// for all 50 members
}
But this involves writing a huge amount of 'empty' code, simply to
achieve one very small end.

Thoughts?

--
Larry Lard
Replies to group please

May 16 '06 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"Larry Lard" <la*******@hotmail.com> wrote:
I want to create a class which is like a List<T>, except that whenever
a T is added, it raises an event.

Simple concept, I think, but I can't seem to find a simple execution.


Inherit from Collection<T> in the System.Collections.ObjectModel
namespace and override its InsertItem() method.

-- Barry
May 16 '06 #2

P: n/a
"Larry Lard" <la*******@hotmail.com> a écrit dans le message de news:
11*********************@g10g2000cwb.googlegroups.c om...

|I want to create a class which is like a List<T>, except that whenever
| a T is added, it raises an event.

Look at the System.ComponentModel.BindingList<T> class, it does all that you
appear to want without any effort on your part :-)

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
May 16 '06 #3

P: n/a
Larry Lard wrote:
I want to create a class which is like a List<T>, except that whenever
a T is added, it raises an event.

<...>
But Shadowing Is Bad, and also any client of the class could:

static void Main(string[] args)
{
NotifyingList<String> foo = new NotifyingList<string>();
foo.ItemAdded += StringAdded;

foo.Add("apple");
foo.Add("banana");

// evil client!
((List<string>)foo).Add("pear");

Console.ReadLine();
}


In the case of downcasting to IList and therefore bypassing your add
method, you could explicitly implement IList.Add yourself and just chain
the call to your add method by casting.

I had the exact same problem and solved it by this method.

<...>

HTH
JB
May 17 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.