tags:

views:

3540

answers:

4

Is there a typedef equivalent in C#, or someway to get some sort of similar behaviour? I've done some googling, but everywhere I look seems to be negative. Currently I have a situation similar to the following:

class GenericClass<T> 
{
    public event EventHandler<EventData> MyEvent;
    public class EventData : EventArgs { /* snip */ }
    // ... snip
}

Now, it doesn't take a rocket scientist to figure out that this can very quickly lead to alot of typing (appologies for the horrible pun) when trying to implement a handler for that event. It'd end up being something like this:

GenericClass<int> gcInt = new GenericClass<int>;
gcInt.MyEvent += new EventHandler<GenericClass<int>.EventData>(gcInt_MyEvent);
// ...

private void gcInt_MyEvent(object sender, GenericClass<int>.EventData e)
{
    throw new NotImplementedException();
}

Except, in my case, I was already using a complex type, not just an int. It'd be nice if it was possible to simplify this a little...

Edit: ie. perhaps typedefing the EventHandler instead of needing to redefine it to get similar behaviour.

+24  A: 

No, there's no equivalent of typedef. You can use using directives within one file, e.g.

using CustomerList = System.Collections.Generic.List<Customer>;

but that will only impact that source file.

Fortunately, the example you give does have a fix - implicit method group conversion. You can change your event subscription line to just:

gcInt.MyEvent += gcInt_MyEvent;

:)

Jon Skeet
I always forget that you can do this. Maybe because Visual Studio suggests the more verbose version. But I'm fine with pressing TAB twice instead of typing the handler name ;)
OregonGhost
In my experience (which is scarce), you have to specify the fully qualified type name, for instance:`using MyClassDictionary = System.Collections.Generic.Dictionary<System.String, MyNamespace.MyClass>;`Is it correct? Otherwise it doesn't seem to consider the `using` definitions above it.
tunnuz
@tunnuz: Yes, you're right - I'll update the answer.
Jon Skeet
+2  A: 

I think there is no typedef. You could only define a specific delegate type instead of the generic one in the GenericClass, i.e.

public delegate GenericHandler EventHandler<EventData>

This would make it shorter. But what about the following suggestion:

Use Visual Studio. This way, when you typed

gcInt.MyEvent +=

it already provides the complete event handler signature from Intellisense. Press TAB and it's there. Accept the generated handler name or change it, and then press TAB again to auto-generate the handler stub.

OregonGhost
Yea, that's what I did to generate the example. But coming back to look at it again AFTER the fact can still be confusing.
Matthew Scharley
I know what you mean. That's why I like to keep my event signatures short, or get away from the FxCop recommendation to use Generic EventHandler<T> instead of my own delegate type. But then, stick with the short-hand version provided by Jon Skeet :)
OregonGhost
If you've got ReSharper, it'll tell you that the long version is overkill (by colouring it in grey), and you can use a "quick fix" to get rid of it again.
Roger Lipscombe
A: 

Jon really gave a nice solution, I didn't know you could do that!

At times what I resorted to was inheriting from the class and creating it's constructors. E.g.

public class FooList : List<Foo> { ... }

Not the best solution (unless your assembly gets used by other people), but it works.

Jonathan C Dickinson
+1  A: 

C# supports some inherited covariance for event delegates, so a method like this:

void LowestCommonHander( object sender, EventArgs e ) { ... }

Can be used to subscribe to your event, no explicit cast required

gcInt.MyEvent += LowestCommonHander;

You can even use Linq syntax and the intellisense will all be done for you:

gcInt.MyEvent += (sender, e) =>
{
    e. //you'll get correct intellisense here
};
Keith
I seriously need to getting around to having a good look at Linq... for the record though, I was building for 2.0 at the time (in VS 2008 though)
Matthew Scharley
Oh, also, I can subscribe fine, but then to get at the event arguments I need an explicit cast, and preferably type checking code, just to be on the safe side.
Matthew Scharley
The syntax is correct, but I wouldn't say it's "Linq syntax"; rather it is a lambda expression. Lambdas are a supporting feature that make Linq work, but are completely independent of it. Essentially, anywhere you can use a delegate, you can use a lambda expression.
Scott Dorman
Fair point, I should have said lambda. A delegate would work in .Net 2, but you'd need to explicitly declare the nested generic type again.
Keith