Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are open generic types considered concrete? How can we qualify abstraction by parameterization?

You can't create an instance of an type that contains generic parameters.

However, it isn't abstract or an interface.

I was reading the StructureMap TypeExtensions helpers and I came across:

public static bool IsConcrete(this Type type)
{
    return (!type.IsAbstract && !type.IsInterface);
}

I'm not really happy with the way that's interpreted, because to it seems like if a type is concrete, then it should be possible for there to be an instance of it. For example, I have trouble considering something like typeof(List<>).MakeGenericType(typeof(List<>).MakeGenericType(typeof(List<>))) to be a concrete type.

I understand that an open generic type in C# and an abstract type in C# are very different in the way that they how they deviate from concretion, but at the same time, there is something fundamentally abstract about both of them. Abstract classes and interface could be interpreted as parameterized if you consider that their parameters are operation implementations. However, this is going a little off topic.

What I really want to know is a way to unify these concepts with consistent semantics that don't feel like a lie where an abomination like List<List<List<>>> can be concrete. Do we have a universal way to describe this distinction?

like image 533
smartcaveman Avatar asked Oct 06 '22 16:10

smartcaveman


2 Answers

I'm not sure if your question is more about the philosophical aspect of parametric vs subtype polymorphism (which I'm not knowledgeable enough in type theory to answer).

I choose to read it in a very practical way as follows, hoping it's what you wanted to know:

given that "concrete" implies "I can create instances of it [*]" and that you can't create an instance of a generic type if it's not parametrized, the given definition of IsConcrete fails to take generic types into account. So, how can you extend IsConcrete in such a way that

  • IsConcrete(typeof(List<>)) is false
  • IsConcrete(typeof(List<int>)) is true
  • IsConcrete(typeof(typeof(List<>).MakeGenericType(typeof(List<>).MakeGenericType(typeof(List<>)))) is false?

For that you can use Type.ContainsGenericParameters

A quick LinqPad snippet to demonstrate:

var TListGen = typeof(List<>);
var TListInt = typeof(List<int>); // this would be "concrete" in the sense
                                  // that its generic arguments
                                  // are all parametrized
var TTest = typeof(List<>).MakeGenericType(typeof(List<>).MakeGenericType(typeof(List<>)));                                     


(!TListGen.ContainsGenericParameters).Dump(); // False
(!TListInt.ContainsGenericParameters).Dump(); // True
(!TTest.ContainsGenericParameters).Dump(); // False

* with some gotchas e.g. concrete types that have a private constructor

like image 79
Paolo Falabella Avatar answered Oct 10 '22 03:10

Paolo Falabella


I think the following statement is not "completely" correct:

You can't create an instance of an type that contains generic parameters

Generic class is actually a template of a class (not of object). And unless that template is converted to a closed class no instance (object) could be created.

But, because we havent specified type to a generic template it does not define it to be concrete/abstract. We can create instance of a generic type, as long as it is not abstract (or interface)!

Not sure if this helps.

like image 30
Manish Basantani Avatar answered Oct 10 '22 01:10

Manish Basantani