Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the base type of an open generic type not open?

Tags:

c#

reflection

Consider a piece of the code below:

public class A<T> { }

public class B<T> : A<T> { }

In such case:

var a = typeof(A<>).GenericTypeArguments.Length;

a has the value 0, which is not surprising. This, however, is somehow unexpected for me:

var b = typeof(B<>).BaseType.GenericTypeArguments.Length;

where b has the value 1. So it is closed using a non-existing type of name "T" and only doing GetGenericTypeDefinition on it makes it open again. Why is that?

like image 952
konrad.kruczynski Avatar asked Aug 19 '15 09:08

konrad.kruczynski


People also ask

What is an open generic?

The C# language defines an open type to be a type that's either a type argument or a generic type defined with unknown type arguments: All types can be classified as either open types or closed types. An open type is a type that involves type parameters. More specifically: A type parameter defines an open type.

What are closed generics?

As noted in the Subsequent Procedures Policy Development Process Working Group (SubPro PDP WG) Final Report, a closed generic is "a TLD representing a string that is a generic name or term under which domains are registered and usable exclusively by the registry operator or its affiliates."

Where t is generic c#?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.

What is unbound generic type?

An unbound type refers to the entity declared by a type declaration. An unbound generic type is not itself a type, and cannot be used as the type of a variable, argument or return value, or as a base type. The only construct in which an unbound generic type can be referenced is the typeof expression (§11.7. 16).


1 Answers

So it is closed using a non-existing type of name "T" and only doing GetGenericTypeArgument on it makes it open again. Why is that?

Because there is one type argument provided - the type parameter to B.

Look at how you're specifying the base class:

public class B<T> : A<T>

What's the T in A<T> if it's not a type argument? Just because the type argument is itself a type parameter doesn't mean it's not being specified as a type argument.

Consider this:

public class A<T1, T2> { }

public class B<T> : A<T, int> { }

Here, the base class of B<T> is A<T, int> - and you can determine that the int has been specified by asking for the type arguments. You can also show where the T comes from:

using System;
using System.Reflection;
using System.Collections.Generic;

public class A<T1, T2> { }

public class B<T> : A<T, int> { }

class Program
{
    static void Main()
    {
        var bT = typeof(B<>).GetTypeInfo().GenericTypeParameters[0];
        var listT = typeof(List<>).GetTypeInfo().GenericTypeParameters[0];
        var bBaseArguments = typeof(B<>).BaseType.GenericTypeArguments;
        Console.WriteLine(bBaseArguments[0] == bT); // True
        // Shows that the T from B<T> isn't the same as the T from List<T>
        Console.WriteLine(bBaseArguments[0] == listT); // False
        Console.WriteLine(bBaseArguments[1] == typeof(int)); // True
    }
}
like image 93
Jon Skeet Avatar answered Oct 20 '22 12:10

Jon Skeet