2

I have a generic method that has some parameter of a generic Type. What I want to do, is be able to access the method on this generic type parameter inside my function.

    public void dispatchEvent<T>(T handler, EventArgs evt)
        {
            T temp = handler; // make a copy to be more thread-safe
            if (temp != null)
            {
                temp.Invoke(this, evt);
            }
        }

I want to be able to call the Invoke method on temp, which is of type T. Is there a way to do this?

Thank You.

Didier A.
  • 4,609
  • 2
  • 43
  • 45
  • Creating a copy right there isn't going to make anything more thread safe. It'll be a reference type, the copy will be shallow and you invoke will act on exactly the same object. – Paul Sasik Jul 02 '10 at 21:14
  • It makes it thread-safe because the assignment and check avoids problems that can arise if the handler reference changes (set to null or new assignment somewhere else) between the test for null and the Invoke method call. – AMissico Jul 02 '10 at 21:35
  • @AMissico: `handler` can't change between the test and the invoke call. It's a local variable and already contains a copy of the reference! – dtb Jul 02 '10 at 21:38
  • Unless I am mistaken, which is possible, but I'm pretty sure all you are doing is passing around the pointer to the reference type. So if handler changes temp is going to change as well since they are both just pointing to an object. The reason is that reference types are passed by reference. Meaning your method is only receiving the reference of where to find the object. Hope that is correct and makes sense. – spinon Jul 02 '10 at 21:41
  • @dtb I think that might be wrong though let's wait and see if someone else corrects me. But value types are passed as clones so in that case what you are saying is correct. But with reference types, they are basically just pointers to objects. So all you do when you pass one in to a method is pass the pointer to the object. So when you make a copy like is done in this method you are just making a copy of the pointer. They both are still pointing to the same thing. But let me see if I can find something to confirm that. – spinon Jul 02 '10 at 21:43
  • @spinon. Objects aren't passed to methods at all. Only references to objects are passed to methods. By value, not by reference (unless you specify `ref` or `out`). – dtb Jul 02 '10 at 21:43
  • Also note that adding a target to a multicast delegate does not modify the delegate. It creates a new delegate. – dtb Jul 02 '10 at 21:45
  • i might have explained this wrong, but don'y have time to correct – AMissico Jul 02 '10 at 21:50
  • @dtb That's right. So why did you say earlier that handler can't change between the test and the invoke call. It could change. Let's say I had the following(pseudo code): var myType = new MyType(); async(dispatchEvent(myType, eventArgs)); myType = new MyType2(); Obviously this is making the assumption that there was a slight delay after the assignment to temp and the actual invoke call. But still, internal to his method temp would now be pointing to MyType2 instead of MyType correct. Since all he did was assign the pointer to temp? – spinon Jul 02 '10 at 21:52
  • @spinon, no, temp would still point to MyType. It goes like this: (The name myType) points to (a reference value that) points to (an instance of MyType). A copy of the second part is given to async(). Later the myType is changed to point to a reference to a MyType2, but async already has a reference to a MyType. async is not aware of the variable named myType at all. – Bart van Heukelom Jul 02 '10 at 22:29
  • Ok Bart my last comment wasn't really correct. In that case I was wrong because a copy of the pointer was passed. What you are saying is correct. Sorry about that. But I still wonder about this situation: Let's say I do what I wrote in the previous comment but I don't reassign anything to the myType variable holding the pointer. But instead I change a property of the myType. Then inside my dispatchEvent method I would see the updated change correct? Or if I change it in the dispatchEvent the myType variable would have that updated value? – spinon Jul 02 '10 at 22:54
  • @spinon: This sounds like a good question to ask at StackOverflow :-) – dtb Jul 02 '10 at 23:13
  • I know right. I guess I will pop this out to it's own question and we can get some community input to see what the answer is. Thanks for putting up with the questions. – spinon Jul 02 '10 at 23:22
  • dtb is correct. You do not need to make a copy because `handler` is already a copy. "`handler` can't change between the test and the invoke call. It's a local variable and already contains a copy of the reference!" – AMissico Jul 02 '10 at 23:24
  • @spinon: I believe so but ask question, then post link in this comments. – AMissico Jul 02 '10 at 23:26
  • Ok so there was already a question. At least it seems close enough that I am not going to bother with a new question: http://stackoverflow.com/questions/3040170/c-passing-objects-and-list-of-objects-by-reference Plus the man Jon Skeet answered and seems pointless to try and get anything else since he is the top around here. – spinon Jul 02 '10 at 23:29

3 Answers3

5

Use a constraint for the generic:

public void dispatchEvent<T>(T handler, EventArgs evt) where T : yourtype
spinon
  • 10,760
  • 5
  • 41
  • 59
2

You might be after something more like:

        public void dispatchEvent<T>(EventHandler<T> handler, T evt) 
            where T: EventArgs
        {
            if (handler != null)
                handler(this, evt);
        }

Just for fun, here it is as an extension method:

    public static void Raise<T>(this EventHandler<T> handler, Object sender, T args)
        where T : EventArgs
    {
        if (handler != null)
            handler(sender, args);
    }
Dan Bryant
  • 27,329
  • 4
  • 56
  • 102
  • @dtb, Thanks, missed that. Got rid of the local copy while I was at it, since it's pointless in this case (already copied in parameter.) – Dan Bryant Jul 02 '10 at 22:07
  • Yep, this did the trick. Have no idea what extension methods are though?!? – Didier A. Jul 02 '10 at 23:09
  • @didibus: Have a look at http://msdn.microsoft.com/en-us/library/bb383977.aspx I'm not sure if extension methods work with `event` members though. – dtb Jul 02 '10 at 23:09
0

How about this :

    public void dispatchEvent<T>(T handler, EventArgs evt)
    {
        T temp = handler; // make a copy to be more thread-safe
        if (temp != null && temp is Delegate)
        {
            (temp as Delegate).Method.Invoke((temp as Delegate).Target, new Object[] { this, evt });
        }
    }
decyclone
  • 30,394
  • 6
  • 63
  • 80