Groups | Blog | Home
all groups > c# > december 2005 >

c# : Generic parameter deduction



Andreas Mueller
12/24/2005 8:21:13 PM
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
--
To email me directly, please remove the *NO*SPAM* parts below:
Jon Skeet [C# MVP]
12/24/2005 9:09:39 PM
[quoted text, click to view]

<snip>

[quoted text, click to view]

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...

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Andreas Mueller
12/25/2005 1:10:59 PM
[quoted text, click to view]

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.

[quoted text, click to view]
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
--
To email me directly, please remove the *NO*SPAM* parts below:
Jesse McGrew
12/25/2005 11:03:20 PM
Please do submit a feature request. I've wished for the same thing.

Jesse
Jon Skeet [C# MVP]
12/26/2005 6:59:19 AM
[quoted text, click to view]

Yup.

[quoted text, click to view]

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.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
AddThis Social Bookmark Button