Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic type constraint of new() and an abstract base class

Here we have a simple class herarchy, and use of generics with a type constraint of new()

public abstract class Base 
{
}

public class Derived : Base
{
}

public class TestClass
{
    private void DoSomething<T>(T arg) where T : new()
    {
    }

    public void TestMethod()
    {
        Derived d1 = new Derived();
        DoSomething(d1); // compiles

        Base d2 = new Derived();
        DoSomething(d2); // compile error
    }
}

The code fails to compile at the indicated line, with an error of:

'Base' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Foo.DoSomething(T)'

This error is clear and makes sense, but I had hoped that the compiler would understand that all derivations of Base (that could be instantiated at this point) do have a public parameterless constructor.

Would this be theoretically possible for the compiler?

like image 304
Richard Ev Avatar asked Aug 08 '13 12:08

Richard Ev


2 Answers

Alas you have to explicitly give the type

DoSomething<Derived>(d2);

theoretically is not possible to create something that is abstract

like image 137
lordkain Avatar answered Nov 17 '22 06:11

lordkain


new Constraint (C# Reference):

To use the new constraint, the type cannot be abstract.

Calling:

Base d2 = new Derived();
DoSomething(d2);

You are in fact doing:

Base d2 = new Derived();
DoSomething<Base>(d2);

Since the Base is abstract, compilation error occurs.

So, you have to cast explicitly:

Base d2 = new Derived();
DoSomething((Derived) d2);

How could you ensure the compiler, that anyone ever put there something, that is not abstract?

The only manner that I see would be, if we got a keyword like "must-inherit-to-non-astract" and then create public must-inherit-to-non-abstract abstract class Base. After that, the compiler could be sure, that if you put the base instance into your method, that will be in fact a subclass, that is non-abstract and therefore can be instantiated.

like image 2
Ryszard Dżegan Avatar answered Nov 17 '22 05:11

Ryszard Dżegan