Generic parameter deduction

A

Andreas Mueller

Hi all,

I have a method where the compiler is unable to deduce the generic
arguments. Now I'm asking myself if this a bug, or if not, why it isn't
working. The method in question is Foo3:

using System;
using System.Collections.Generic;

namespace ConsoleApplication10
{
class Program
{
class A<T> { }
class B<T> { }

static A<T> Foo1<T, AA>(AA a, T t) where AA : A<T>
{
return default(A<T>);
}
static A<T> Foo2<T, AA>(AA a, B<T> t) where AA : A<T>
{
return default(A<T>);
}
static A<T> Foo3<T, AA>(AA a) where AA : A<T>
{
return default(A<T>);
}
static void Main(string[] args)
{
A<int> ai = new A<int>();

ai = Foo1(ai, 42);
ai = Foo2(ai, new B<int>());

// ... gives CS0411, can't deduce generic parameter. Why?
ai = Foo3(ai);
}
}
}

The compiler can deduce T for Foo1, as it is explicitly defined as a
parameter. It also can infer T & AA in Foo2, although T is only there
implicitly as an generic argument.
But if it can handle Foo2, why not Foo3?

TIA,
Andy
 
J

Jon Skeet [C# MVP]

Andreas Mueller said:
I have a method where the compiler is unable to deduce the generic
arguments. Now I'm asking myself if this a bug, or if not, why it isn't
working. The method in question is Foo3:

static A<T> Foo3<T, AA>(AA a) where AA : A<T>
{
return default(A<T>);
}

Looking at section 27.6.4 of the draft ECMA spec (the numbering keeps
changing, unfortunately - "Inference of type arguments" is the sub-
clause name) gives *some* light.

Each argument/parameter is processed in turn. Fortunately, we've only
got one to deal with here - the parameter of "AA a" and the argument of
"ai" (with type A<int>).

Given that AA is a method type parameter, it *looks* like we should go
for the option which says that type inference succeeds for this
parameter, and the type of AA is A<int>.

Unfortunately, I don't see anything in the spec which says that
inference should then take the constraints into account and further
infer what it can (in this case that T is int).

In neither Foo1 nor Foo2 is the constraint needed to work out T, which
is why there isn't a problem. (In the case of Foo2, the second
parameter is of a constructed type, and the last option in the spec
occurs, inferring T.)

I don't know whether this is the answer you were hoping for, and I'm
not *100%* sure it's right - I've been reading the spec quite a lot
recently, so I'm reasonably "in tune" with it, but there are some
tricky bits like this...
 
A

Andreas Mueller

Jon said:
Looking at section 27.6.4 of the draft ECMA spec (the numbering keeps
changing, unfortunately - "Inference of type arguments" is the sub-
clause name) gives *some* light.

Each argument/parameter is processed in turn. Fortunately, we've only
got one to deal with here - the parameter of "AA a" and the argument of
"ai" (with type A<int>).

Given that AA is a method type parameter, it *looks* like we should go
for the option which says that type inference succeeds for this
parameter, and the type of AA is A<int>.

Unfortunately, I don't see anything in the spec which says that
inference should then take the constraints into account and further
infer what it can (in this case that T is int).

I think that is the point, it needs the constraint to resolve the
parameter. If it is not spec'd, it is not a bug, but a feature request.
In neither Foo1 nor Foo2 is the constraint needed to work out T, which
is why there isn't a problem. (In the case of Foo2, the second
parameter is of a constructed type, and the last option in the spec
occurs, inferring T.)

I don't know whether this is the answer you were hoping for, and I'm
not *100%* sure it's right - I've been reading the spec quite a lot
recently, so I'm reasonably "in tune" with it, but there are some
tricky bits like this...
Hi Jon,

this answer really helped me! What do you think about it? Should it
work? (I'm a bit spoiled from C++ templates, so I'd say yes :) ).I'll
reread the spec and may log a feature request at MS.

Cheers,
Andy
 
J

Jon Skeet [C# MVP]

Andreas Mueller said:
I think that is the point, it needs the constraint to resolve the
parameter. If it is not spec'd, it is not a bug, but a feature request.
Yup.


this answer really helped me! What do you think about it? Should it
work? (I'm a bit spoiled from C++ templates, so I'd say yes :) ).I'll
reread the spec and may log a feature request at MS.

You certainly might as well. I've made a note for the specification
committee, but in more of a "note that this means" rather than "this
should be fixed" way - MS is probably a better avenue for that.
 

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