Generic delegate type not inferred by compiler?

A

Adam Clauss

I feel like the compiler should be able to infer the type of the
parameter to this generic delegate, but it requires me to specify the
type parameter. Am I just "wrong", or did I do something wrong in the
definition/use?

public delegate void MyDelegate<TSomeType>(TSomeType a);

public class MyClass
{
public void useDelegate<TSomeType>(MyDelegate<TSomeType> del)
{
}

public void a()
{
useDelegate(delegateMethod); // *** THROWS ERROR CS0411
useDelegate<string>(delegateMethod); // COMPILES OK
}

public void delegateMethod(string str)
{
}
}

Thanks,
Adam
 
P

Peter Duniho

I feel like the compiler should be able to infer the type of the
parameter to this generic delegate, but it requires me to specify the
type parameter. Am I just "wrong", or did I do something wrong in the
definition/use?

I do not believe that type inference propagates like that. In particular,
you are asking the compiler to infer a type parameter for the generic
method from a type parameter that you also want inferred from a type
parameter for a generic type.

Since type inference is about inferring type parameters for generic
_methods_, it doesn't cover inferences made for generic types. That is,
C# won't infer type parameters for generic types, only for generic
methods, whereas your example would require an inference for a generic
type as well.

In your example, supplying the necessary type parameter is the most
concise solution. But, if you happened to have a concrete instance of the
generic delegate type (e.g. stored in a variable declared of the right
type), you could use that and have the generic method's type parameter
inferred from that. For example:

public void a()
{
MyDelegate<string> action = delegateMethod;

useDelegate(action);
}

See section 7.4.2 of the C# 3.0 specification for more details.

Pete
 
H

Harlan Messinger

Adam said:
I feel like the compiler should be able to infer the type of the
parameter to this generic delegate, but it requires me to specify the
type parameter. Am I just "wrong", or did I do something wrong in the
definition/use?

public delegate void MyDelegate<TSomeType>(TSomeType a);

public class MyClass
{
public void useDelegate<TSomeType>(MyDelegate<TSomeType> del)
{
}

public void a()
{
useDelegate(delegateMethod); // *** THROWS ERROR CS0411
useDelegate<string>(delegateMethod); // COMPILES OK
}

public void delegateMethod(string str)
{
}
}

I think, if for no other reason, this inference would be impossible
because of overloading. What if, in addition, you also had

public void delegateMethod(int i)
{
}

? The compiler wouldn't know whether to instantiate

MyDelegate<string>(string a)

or

MyDelegate<int>(int a)

Therefore, you have to indicate the method's type explicitly, via the
explicit delegate.
 
P

Peter Duniho

I think, if for no other reason, this inference would be impossible
because of overloading. What if, in addition, you also had

public void delegateMethod(int i)
{
}

? The compiler wouldn't know whether to instantiate

MyDelegate<string>(string a)

or

MyDelegate<int>(int a)

Well, yes. But it's not an overloading problem. It's the inability to
infer the correct delegate type. Type inference works only for generic
methods; a method group (e.g. "delegateMethod") cannot be used as a value
for a delegate unless the type of delegate is already known. There's no
inference that will allow the compiler to pick the correct delegate type.
And of course, if you write enough code for the delegate type to be known,
type inference on the generic method isn't a problem at all (the compiler
resolves the overloading at the point where you've specified the delegate
type).

You can tell it's not an overloading problem, because you get the same
error whether the method is overloaded or not. If it were an overloading
problem, then you would get an error only when the method really is
overloaded.

Pete
 
H

Harlan Messinger

Peter said:
Well, yes. But it's not an overloading problem. It's the inability to
infer the correct delegate type. Type inference works only for generic
methods; a method group (e.g. "delegateMethod") cannot be used as a
value for a delegate unless the type of delegate is already known.
There's no inference that will allow the compiler to pick the correct
delegate type. And of course, if you write enough code for the delegate
type to be known, type inference on the generic method isn't a problem
at all (the compiler resolves the overloading at the point where you've
specified the delegate type).

You can tell it's not an overloading problem, because you get the same
error whether the method is overloaded or not. If it were an
overloading problem, then you would get an error only when the method
really is overloaded.

That reasoning doesn't lead to that conclusion. They could just as well
have decided that since this kind of inference is impossible as soon as
the method is overloaded, it was easier just not to provide that kind of
inference at all, rather than provide it in the non-overloaded case.
 
P

Peter Duniho

That reasoning doesn't lead to that conclusion. They could just as well
have decided that since this kind of inference is impossible as soon as
the method is overloaded, it was easier just not to provide that kind of
inference at all, rather than provide it in the non-overloaded case.

Well, if you get the C# design team to explain it that way, I'm on board
with that explanation. In the meantime, since the compiler does just bail
on impossible overload resolutions, without dropping all overload support
altogether, I find the conjecture to be an unlikely explanation.
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
Well, yes. But it's not an overloading problem. It's the inability to
infer the correct delegate type. Type inference works only for generic
methods; a method group (e.g. "delegateMethod") cannot be used as a value
for a delegate unless the type of delegate is already known. There's no
inference that will allow the compiler to pick the correct delegate type.

since, of course, that method group (even with no overloads) could
successfully convert to MyDelegate<string>, Action<string>, etc, etc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top