views:

81

answers:

3

C# chokes on

delegate void Bar<T>(T t);

void foo(Bar bar)
{
    bar.Invoke("hello");
    bar.Invoke(42);
}

The workaround is to use an interface

interface Bar
{
    void Invoke<T>(T t);
}

but now I need to go out of my way to define the implementations of the interface. Can I achieve the same thing with delegates and simple methods?

A: 

Maybe your example does not quite illustrate your intention but what is the point of generics here? You are not using the the type T in any useful manner and I would be using object instead of T.

Aliostad
It may be his intention to assign an open generic method to the delegate. C# does not currently allow this.
Timwi
I cannot see the benefit. What is the benefit instead of using plain object?
Aliostad
@Aliostad: Static typing. Compile-time type checking.
Timwi
+3  A: 

This is not possible because you cannot assign an open generic method to a delegate. It would be an interesting new feature to suggest, but currently C# does not allow it.

Possible workarounds:

delegate void Bar(object t);

void foo(Bar bar)
{
    bar.Invoke("hello");
    bar.Invoke(42);
}

void BarMethod(object t)
{
    if (t is int)
        // ...
    else if (t is string)
        // ...
}

foo(BarMethod);

delegate void Bar<T>(T t);

void foo(Bar<string> stringBar, Bar<int> intBar)
{
    stringBar.Invoke("hello");
    intBar.Invoke(42);
}

void BarMethod<T>(T t)
{
    // ...
}

foo(BarMethod<string>, BarMethod<int>);

The interface workaround you already mentioned:

interface IBar
{
    void Invoke<T>(T t);
}

void foo(IBar bar)
{
    bar.Invoke("hello");
    bar.Invoke(42);
}

class BarType : IBar
{
    public void Invoke<T>(T t)
    {
        // ...
    }
}

foo(new BarType());
Timwi
The solutions listed are fine, but the problem has not been correctly identified. I do not see where in the OP's code an attempt is made to assign a "an open generic method to a delegate". The OP's code does not compile because one cannot declare a *reference* to an instance of an open generic delegate-type without a generic type parameter (except in a generic class). Alternatively one could say that there is no type called `Bar` in the OP's code. There *is* a type called `Bar<>`, but it would not be possible for `foo` to accepted a parameter of this type without making the method generic.
Ani
@Ani: I thought a step further than you. Imagine you *could* have an instance of an open generic delegate type (irrespective of whether it’s called `Bar` or has some special syntax). What would you assign to it? An open generic method, of course.
Timwi
A: 

I can see some usefulness to having e.g. a "SerializeSomething(thing as T)" routine which would have a type it could pass along to other generics. Unfortunately, I think such a delegate would have to have some extra type information associated with it to make such generics work. For example, the type T may not be the actual type of "thing". If "thing" is declared as SomeBaseType but is actually a DerivativeOfSomeBaseType, the code SerializeSomething(thing) will call SerializeSomething(thing). I know of nothing means in the delegate mechanism by which type SomeBaseType would get passed to the target of a delegate.

supercat