1

The answers in this question claim that it is impossible to specify a default type argument that will be used if the consumer of the generic class does not specify a type.

But when addressing the raising of an event using the pre-defined generic EventHandler delegate... if you have no use for any data that might be passed within the EventArgs parameter, you do not actually have to specify a type argument. In other words, instead of using public event EventHandler<TEventArgs> EventDelegate;, you can just use public EventHandler EventDelegate;

In my extremely limited use of generics, I have found it to be impossible to use a generic class without specifying a type argument, and the answers given in response to the linked question would agree with this, so how is it that the predefined generic EventHandler<TEventArgs> delegate violates this rule?

Community
  • 1
  • 1
TimFoolery
  • 1,895
  • 1
  • 19
  • 29

1 Answers1

6

No. That's not a 'default' value. EventHandler and EventHandler<T> are completely different types. Same thing goes for IEnumerable and IEnumerable<T> and all the other similarly named types that exhibit this pattern.

You can roll your own version of this pretty easily.

class MyType
{
    void Foo(object obj) ...
}

class MyType<T> : MyType
{
    void Foo(T obj)
    {
        base.Foo(obj);
    }
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Disregard my previous comment. I must've made a mistake when attempting to overload the class name. By defining two classes, a non-generic `MyStack` and generic `MyStack`, I was able to simulate this behavior. It seems odd to me that you can't overload a generic class by using a different number of type parameters, but you can overload the class name with a generic and non-generic class. `MyStack` and `MyStack` can coexist, but `MyStack` and `MyStack` cannot. Seems strange to me! – TimFoolery Mar 13 '13 at 05:34
  • You can't technically 'overload' the class. But you can define separate versions of it with anywhere from 0 upto several thousand parameters. See `Action<...>` for a practical example of this. – p.s.w.g Mar 13 '13 at 05:37
  • PS: Regarding the example you gave in your answer, is the benefit of doing it that way not having to reproduce the code that exists in the base class, while still managing to restrict the types allowed into an instance of `MyType` to `T`? PSS: GRRR... in my previous comment, `MyStack` was meant to be `MyStack` – TimFoolery Mar 13 '13 at 05:38
  • That's the gist of it, but there are other benefits. You can have a `MyType[]` that contains both `MyType` and `MyType`. Without that non-generic base class, there's no way to make a type-safe, heterogenous collection of `MyType<>`. – p.s.w.g Mar 13 '13 at 05:42
  • By the way, I don't know what I did wrong to make MyStack and MyStack generate a compiler error, but I went back to that project, and it compiled, so if anyone reads this thread in the future, I'd like to point out that you can, in fact, reuse the same generic class name by using a different number of type parameters, just like you can do so with a delegate class name. Perhaps I made the same typo (leaving out the "T" in the "T, U" parameters) in Visual Studio that I made here in the comments. No clue! – TimFoolery Mar 15 '13 at 18:20