1

I have a data object which I pass around :

public class TimedResult<T>
{
    public ResultRequest Request { get; set; }
    public T Data { get; set; }
    public TimeSpan TimeTaken { get; set; }
}

In my Manager class I have some work done which raises an event :

public void Execute(ResultRequest request)
{
    var result = new TimedResult<DataTable>();
    // fill data object here
    OnResult(result);
}

I have made the OnResult method generic :

protected virtual void OnResult<T>(TimedResult<T> result)
{
    if (Result != null)
        Result(this, result);
}

But how do I make the event declaration generic?

public event EventHandler<TimedResult<T>> Result; // red line under T

How should I be doing this?

sprocket12
  • 5,368
  • 18
  • 64
  • 133
  • Where does `T` come from? It should be part of the class definition `class Manager` – lc. Oct 03 '14 at 10:23
  • @lc. good question, I am not too familiar with generics, I guess what I want to do is to be able to return `TimedResult` as well as `TimedResult` using the same `OnResult` method and event. – sprocket12 Oct 03 '14 at 10:25
  • @Muhammad then your best bet is to use `object`, i.e. `public event EventHandler> Result;` ;p – Marc Gravell Oct 03 '14 at 10:29
  • This is a bit XY but looking at this quickly, I think you're trying to execute something asyncronously and return the result. Why not just use TPL? Return an awaitable Task in the `Execute` method and you don't need the event at all: `public async Task Execute(ResultRequest request) {...}`. Of course I'm assuming the one doing the executing will be the one listening for the result. – lc. Oct 03 '14 at 10:30
  • @MarcGravell yes that is what I had in place before I decided to randomly stick a T in there for good measure :D – sprocket12 Oct 03 '14 at 10:30

2 Answers2

2

Event declarations cannot be (open) generic. They can use generic type parameters from the declaring type, but they cannot declare their own generic parameters. So what you want is only possible if the type that declares Result has a T (either directly, or via an outer-type), i.e. if this is SomeManager<T>:

class SomeManager<T> {
     public event EventHandler<TimedResult<T>> Result;
}

then the T is whatever it is from above; in SomeManager<int> it will be an EventHandler<TimedResult<int>> and so on.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

But how do I make the event declaration generic?

public event EventHandler<TimedResult<T>> Result; // red line under T

The class which declares the whole event should be also generic (i.e. it should have a generic type parameter):

public class X<TEventData>
{
    public event EventHandler<TimedResult<TEventData>> Result; // red line under T
}

Now, depending on your requirements, this will work or not, because if you're looking for raising the event with more than an event data type, you might solve this raising the event using reflection (avoid this).

Or I would suggest that you should design an interface which should define that any given event data shares some members, give that interface as X<TEventData> TEventData type argument, and cast the interface type to a concrete implementation when needed in your event handlers.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206