Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typeof gives exception 'Type expected` for unconstructed nested generic type

Normally getting an unconstructed generic type is quite easy, using typeof:

Type genericType = typeof( Func<> );

I would expect the following to work as well, but it gives a compiler error Type expected.

Type genericNestedType = typeof( Func<Func<>> );

It's relatively easy to work around this by using Func<Func<object>> instead. However, where you 'consume' the type you then have to remember calling GetGenericTypeDefinition().

A scenario where you would want to 'fill up' all non-assigned generic type parameters wouldn't be possible. Again, it would be relatively easy to create a dummy type instead to indicate those parameters. (e.g. Func<Func<ToReplace, object, int>>)

Is there any reason why typeof doesn't work on nested generic unconstructed types?

like image 364
Steven Jeuris Avatar asked Nov 04 '11 19:11

Steven Jeuris


1 Answers

I don't believe this is a compiler bug - section 7.6.11 of the C# 4 spec (the typeof operator) doesn't seem to give any syntax which would lead it to be valid; Func<Func<>> is neither a valid type construction, nor a valid unbound-type-name construction.

As to why that's the case though: my guess is that it's very rarely needed (I've never even thought of using it before, nor heard anyone requesting it) and so the additional complexity in language design, compiler implementation and testing has been considered to outweigh the benefit. This is often the case with "why doesn't C# have feature X" questions, as Eric Lippert is fond of pointing out :)

I was pleasantly surprised to see that it is possible to do at execution time:

Type unbound = typeof(Func<>);
Type partiallyBound = unbound.MakeGenericType(new[] { unbound });
Console.WriteLine(partiallyBound);        

I was half expecting it to be invalid in the .NET type system, although I expect that could have caused other problems.

like image 186
Jon Skeet Avatar answered Nov 07 '22 11:11

Jon Skeet