tags:

views:

136

answers:

3
class Program
{
    static void Main(string[] args)
    {
        Type t = typeof(A<,>);
        Console.WriteLine(typeof(A<,>)); // prints A'2[T1,T2]
    }    
}

class A<T1,T2>
{

}

As far as I know, generic type A<T1, T2> is not an actual type, but rather a blueprint/template for an actual type, so why does typeof accept it as a parameter (since as far as I know, typeof accepts as parameter actual types)?

Thank you

+4  A: 

It is accepted because it is a generic type.

It is an open generic type (where they type parameters have not been specified), but a type none the less.

See the discussion here (What exactly is an “open generic type”).

And on MSDN (typeof):

The typeof operator can also be used on open generic types.

Oded
1-Would you agree that strictly speaking A<T1,T2> is not an actual type? 2-What is the difference between open generic type and open constructed generic type?
flockofcode
@flockofcode - 1. open generic types are types. They cannot be instantiated without supplying type parameters, but they are still types. 2. An open constructed type is when at least one of the generic types has not been specified. See here: http://en.csharp-online.net/Generic_types
Oded
1)"open generic types are types" As far as i can tell, there's no way for method to have as one of its parameters an open constructed generic type? 2) So we say that A<T,int>{} is an open constructed type, while A<T,T1> is open generic type. But couldn't we argue that A<T,T1> is also an open constructed type (if not, then definition of an open constructed type should say that open constructed type must have at least one of its type arguments specified, else it is an open generic type )?!
flockofcode
@flockofcode - 1. Why not? The formal parameter can be an open constructed generic type. During runtime, you will of course have to pass through a closed generic type. 2. I would say that open constructed generic types are a subset of open generic types. So, some open constructed generic types are also open generic types.
Oded
@flockofcode you could kind of think of an open generic type as abstract - it's a non-instantiable base upon which concrete generic types are constructed.
Rex M
"1. Why not? The formal parameter can be an open constructed generic type. During runtime, you will of course have to pass through a closed generic type."Could you provide an example?
flockofcode
@flockofcode - `public void MethodAccessException(OpenConstructed<T,int> con){}`. The formal argument is an open constructed generic type. You will have to create an instance with the first type parameter specified and pass that in - `new OpenConstructed<string,int>()`.
Oded
@Oded: You can't do that, but you can do: `public void MethodAccessException<T>(OpenConstructed<T,int> con){}` C# doesn't do type erasure like Java, so when there are undetermined type parameters the method accepting the argument must be generic in some way as well (it could equally be a member of a generic class).
Ben Voigt
@Ben Voigt - quite right. thanks for the correction.
Oded
+1  A: 

Because A<T1, T2> is an open generic, which the documentation explicitly says it supports.

John Weldon
What is the difference between open generic type and open constructed generic type?
flockofcode
+4  A: 

In reflection the unconstructed generic type, say C<> is conflated with the instance type C<T>.

This is perhaps less than theoretically pure; I think of these as very different entities. I think of one as the symbol "C with one type parameter" and the other as a compile time type C<T>. In code, C<> and C<T> are not synonyms for each other; you can make a field of the latter type if T is in scope, but you cannot ever make a field of the former type.

That the reflection library gives you the type of the instance type when you ask for the unconstructed type is not all bad though. What would you do with the unconstructed type? There's nothing you really can do with it. But with the instance type, you can say "substitute int for T" in here.

The real benefit of getting C<T> when you ask for typeof(C<>) is that this always gives you the unconstructed type. Compare:

class C<T>
{
    public static Type CT() { return typeof(C<T>); }
    public static Type JustC() { return typeof(C<>); }
}

When you call CT, what are you going to call it on? There's no type C<T> to call CT on. You can call C<int>.CT in which case you'll get back C<int>, not C<T>. The only way to get the type C<> constructed with T is to ask for typeof(C<>).

Does that make sense?

I haven't yet covered reflection ( I have a vague idea of what it is )

Reflection is simply the library of code that allows you to get information about your code in the code itself. "typeof" gives you a Type object which you can then "reflect" upon to find out information about the type.

I'm not sure I understand what you mean by "even when T is not in scope"

The way I said it was confusing. I've rephrased it.

Eric Lippert
1 - "Does that make sense?" Somewhat, but I haven't yet covered reflection ( I have a vague idea of what it is ) and I'm more on a stupid side.2 - "The real benefit then is that typeof(C<>) lets you obtain the type object for C<T> even when T is not in scope" I'm not sure I understand what you mean by "even when T is not in scope"?2 - "That the reflection library gives you the type of the instance type when you ask for the unconstructed type is not all bad though. "I assume that here you're not talking about typeof(A<,>), since this doesn't give you an instance of type A<T,T1>
flockofcode
"That the reflection library gives you the type of the instance type when you ask for the unconstructed type is not all bad though."Terminology you use is a bit confusing. You say typeof(C<>) returns the type of an instance type, thus it returns the type of C<T>, where T is not yet specified. Thus to my understanding you’re implying that C<T> is an instance type, while to my knowledge instance types have all their type parameters determined?!
flockofcode
@flockofcode: Indeed, the terminology is *very* confusing. The specification defines the "instance type" of a generic type as the type which is the *compile time* type of the type constructed with its type parameters. For example, in class C<T> { C<T> x; } the *compile time* type of x is the *instance type* of C-with-one-type-parameter. The runtime type of x will of course depend on the type argument substituted for T
Eric Lippert
uhm, I thought instance type of a generic type is just another word for closed constructed generic type,but "the compile time type of x is the instance type of C-with-one-type-parameter.The runtime type of x will of course depend on the type argument substituted for T" suggests that is not the case
flockofcode
@flockofcode: I refer you to section 10.3.1 of the C# specification.
Eric Lippert
ok, thank you all for your help
flockofcode