Capturing Dictionary<T>.Add() event?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Brett Romero

    Capturing Dictionary<T>.Add() event?

    If I want to take action on the Add event of a generic Dictionary, do I
    need to create a custom Dictionary and add an event handler for the
    Add() method? The dictionary is a public field on a custom control.

    Thanks,
    Brett

  • Brett Romero

    #2
    Re: Capturing Dictionary&lt;T &gt;.Add() event?

    I went ahead with adding an Add() event handler. If any one is
    interested:

    public class CustomDictionar y<TKey, TValue> : Dictionary<TKey ,
    TValue>
    {
    public event AddEventHandler AddEvent;

    public CustomDictionar y()
    {

    }

    public void Add(TKey pKey, TValue pValue)
    {
    if( AddEvent != null )
    AddEvent( new AddEventArgs(pK ey, pValue) );
    base.Add( pKey, pValue );
    }

    public delegate void AddEventHandler ( AddEventArgs
    pAddEventArgs );

    public class AddEventArgs : EventArgs
    {
    private TKey _key;
    private TValue _value;

    public AddEventArgs( TKey key, TValue value )
    {

    }

    public TKey Key
    {
    get
    {
    return _key;
    }
    }

    public TValue Value
    {
    get
    {
    return _value;
    }
    }
    }
    }


    Brett

    Comment

    • Barry Kelly

      #3
      Re: Capturing Dictionary&lt;T &gt;.Add() event?

      "Brett Romero" <account@cygen. com> wrote:
      [color=blue]
      > If I want to take action on the Add event of a generic Dictionary, do I
      > need to create a custom Dictionary and add an event handler for the
      > Add() method? The dictionary is a public field on a custom control.[/color]

      The existing Dictionary<,> generic class uses non-virtual methods for
      speed reasons, for those people who need the speed.

      If you want to intercept these kinds of events, consider descending from
      the KeyedCollection <,> class, or write your own class that implements
      IDictionary<,> and delegates actual storage to a Dictionary<,>.

      -- Barry

      --

      Comment

      • Barry Kelly

        #4
        Re: Capturing Dictionary&lt;T &gt;.Add() event?

        "Brett Romero" <account@cygen. com> wrote:
        [color=blue]
        > I went ahead with adding an Add() event handler. If any one is
        > interested:
        >
        > public class CustomDictionar y<TKey, TValue> : Dictionary<TKey ,
        > TValue>[/color]

        Be careful: any client code can evade your event notification by simply
        casting the dictionary to Dictionary<TKey ,TValue> and calling Add()
        directly. So, if you expect this event to be invoked every time the
        Add() method is called on your public property, you will be
        disappointed!

        -- Barry

        --

        Comment

        • Brett Romero

          #5
          Re: Capturing Dictionary&lt;T &gt;.Add() event?

          >>If you want to intercept these kinds of events, consider descending from
          the KeyedCollection <,> class, or write your own class that implements
          IDictionary<,> and delegates actual storage to a Dictionary<,>.

          I don't notice any difference in performance. Just not enough data or
          use of this to make any difference. I don't need everything that
          IDictionary<,> will require. Rewiring to work with KeyCollection<, >
          isn't worth the effort and I'm unsure if it will in the end accomplish
          what I already have. Inheriting from Dictionary<,> is doing
          everything I need with good performance.

          No one will be casting this either.

          Thanks,
          Brett

          Comment

          • Barry Kelly

            #6
            Re: Capturing Dictionary&lt;T &gt;.Add() event?

            "Brett Romero" <account@cygen. com> wrote:
            [color=blue][color=green][color=darkred]
            > >>If you want to intercept these kinds of events, consider descending from[/color]
            > > the KeyedCollection <,> class, or write your own class that implements
            > > IDictionary<,> and delegates actual storage to a Dictionary<,>.[/color]
            >
            > I don't notice any difference in performance.[/color]

            It's not about performance: it's about code reliability. If you're
            depending on your event being called, people can evade it by casting to
            the base class.
            [color=blue]
            > No one will be casting this either.[/color]

            If it's on a public interface, you can't guarantee anything about how
            it's going to be used, unless it follows the rules of the CLR framework.

            It's easy to cast by accident if you've got worker methods that work
            with IDictionary<,>, for example. I do things like this all the time.
            YMMV!

            -- Barry

            --

            Comment

            • Brett Romero

              #7
              Re: Capturing Dictionary&lt;T &gt;.Add() event?

              I guess I'd need to see an example and explanation of why you'd want to
              cast a generic. Isn't that defeating the purpose? It won't be casted
              in my cast and I can guarantee that. The added complexity of a cast
              will never be used.

              Brett

              Comment

              • Barry Kelly

                #8
                Re: Capturing Dictionary&lt;T &gt;.Add() event?

                "Brett Romero" <account@cygen. com> wrote:
                [color=blue]
                > I guess I'd need to see an example and explanation of why you'd want to
                > cast a generic. Isn't that defeating the purpose? It won't be casted
                > in my cast and I can guarantee that. The added complexity of a cast
                > will never be used.[/color]

                This is contrived to make a point:

                ---8<---
                static public class Util
                {
                public static void AddEntry<TKey,T Value>(
                Dictionary<TKey ,TValue> dict, TKey key, TValue value)
                {
                dict.Add(key, value);
                }
                }
                --->8---

                Pass the dictionary that is part of the public interface of your class
                to this method (Util.AddEntry) , and it will avoid your hook on the Add
                method.

                The cast is implicit, and you can do nothing to guarantee it won't be
                used if the class with this custom dictionary is a public part of a
                library.

                -- Barry

                --

                Comment

                • Brett Romero

                  #9
                  Re: Capturing Dictionary&lt;T &gt;.Add() event?

                  [color=blue]
                  > Pass the dictionary that is part of the public interface of your class
                  > to this method (Util.AddEntry) , and it will avoid your hook on the Add
                  > method.
                  >
                  > The cast is implicit, and you can do nothing to guarantee it won't be
                  > used if the class with this custom dictionary is a public part of a
                  > library.[/color]

                  Not if you add the event there also:

                  static public class Util
                  {
                  public event Mydict.AddEvent Handler AddEvent;

                  public static void AddEntry<TKey,T Value>(
                  Dictionary<TKey ,TValue> dict, TKey key, TValue value)

                  {
                  if( AddEvent != null )
                  Mydict.AddEvent ( new AddEventArgs(pK ey, pValue) );
                  dict.Add(key, value);
                  }
                  }

                  I just can't think of a practical reason why you'd want to do such a
                  thing in the first place. Not to say one doesn't exists.

                  Brett

                  Comment

                  • Barry Kelly

                    #10
                    Re: Capturing Dictionary&lt;T &gt;.Add() event?

                    "Brett Romero" <account@cygen. com> wrote:
                    [color=blue]
                    >[color=green]
                    > > Pass the dictionary that is part of the public interface of your class
                    > > to this method (Util.AddEntry) , and it will avoid your hook on the Add
                    > > method.
                    > >
                    > > The cast is implicit, and you can do nothing to guarantee it won't be
                    > > used if the class with this custom dictionary is a public part of a
                    > > library.[/color]
                    >
                    > Not if you add the event there also:[/color]

                    You're missing the point - I, the client of *your* code, possibly on the
                    other side of the world and speaking in a different language, wrote the
                    AddEntry method *myself*. I have no responsibility to call *your* event.
                    That is what I mean by pointing out that you've got no guarantee that
                    *your* event will be called.

                    -- Barry

                    --

                    Comment

                    • Brett Romero

                      #11
                      Re: Capturing Dictionary&lt;T &gt;.Add() event?

                      Yes - you are correct when I have no control over the environment that
                      this code will be used in. However, I do have complete control so it
                      is a safe bet.

                      Thanks,
                      Brett

                      Comment

                      • Giulio Petrucci

                        #12
                        Re: Capturing Dictionary&lt;T &gt;.Add() event?

                        Hi Barry,
                        Hi everybody,

                        Barry Kelly ha scritto:
                        [color=blue]
                        > Be careful: any client code can evade your event notification by simply
                        > casting the dictionary to Dictionary<TKey ,TValue> and calling Add()
                        > directly. So, if you expect this event to be invoked every time the
                        > Add() method is called on your public property, you will be
                        > disappointed![/color]

                        I agree with your suggestion.
                        I think that the better way is to wrap a Dictionary<TKey ,TValue> with a
                        wrapper class implementing the IDictionary<,> interface, declaring

                        private Dictionary<,> innerDictionary

                        within this new class. So that no one can access the member fo the inner
                        dictionary (without event handling). Am I right? I ask you because I'm
                        quite "new" in C# programming...

                        Thanks,
                        Giulio

                        Comment

                        • Barry Kelly

                          #13
                          Re: Capturing Dictionary&lt;T &gt;.Add() event?

                          Giulio Petrucci <giulio.petrucc i@RIMUOVIspeech village.com> wrote:
                          [color=blue]
                          > Hi Barry,
                          > Hi everybody,
                          >
                          > Barry Kelly ha scritto:
                          >[color=green]
                          > > Be careful: any client code can evade your event notification by simply
                          > > casting the dictionary to Dictionary<TKey ,TValue> and calling Add()
                          > > directly. So, if you expect this event to be invoked every time the
                          > > Add() method is called on your public property, you will be
                          > > disappointed![/color]
                          >
                          > I agree with your suggestion.
                          > I think that the better way is to wrap a Dictionary<TKey ,TValue> with a
                          > wrapper class implementing the IDictionary<,> interface, declaring
                          >
                          > private Dictionary<,> innerDictionary
                          >
                          > within this new class. So that no one can access the member fo the inner
                          > dictionary (without event handling). Am I right? I ask you because I'm
                          > quite "new" in C# programming...[/color]

                          Sure. And the KeyedCollection <T> class already does most of what most
                          people require, so that they simply need to override the InsertItem/ etc
                          methods.

                          -- Barry

                          --

                          Comment

                          Working...