2013-08-08 3 views
10

Здесь мы имеем простой класс herarchy и использование дженериков с type constraint из new()Generic тип ограничения нового() и абстрактный базовый класс

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 
    } 
} 

код не удается скомпилировать в указанной строке, ошибка:

«Base» должна быть не абстрактный типом с конструктором общественным того, без параметров, чтобы использовать его в качестве параметра «T» в универсальном типе или методе «Foo.DoSomething (Т)»

Эта ошибка ясна и имеет смысл, но я надеялся, что компилятор поймет, что все производные от Base (которые могут быть созданы на данный момент) имеют открытый конструктор без параметров.

Будет ли это теоретически возможным для компилятора?

+0

Эта строка беспокоит меня более «не абстрактным типом», чем предложение конструктора без параметров. –

ответ

8

Увы, вы должны явно дать тип

DoSomething<Derived>(d2); 

теоретически невозможно создать что-то, что является абстрактным

+5

Мне нравится «теоретически» часть. Заставляет меня чувствовать, что Джон Скит появится, сделайте волшебство, и там вы идете, созданный абстрактный объект. –

+0

На какой версии .NET он компилируется, если d2 объявлен как абстрактный Base? –

1

new Constraint (C# Reference):

Чтобы использовать новое ограничение, тип не может быть Абстрактные.

Вызов:

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

Вы на самом деле делает:

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

Поскольку Base является абстрактным, возникает ошибка компиляции.

Таким образом, вы должны бросить в явном виде:

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

Как вы могли убедиться, компилятор, что кто-нибудь положить туда что-то, что не абстрактно?

Единственное, что я вижу, было бы, если бы мы получили ключевое слово как «must-inherit-to-non-astract», а затем создали public must-inherit-to-non-abstract abstract class Base. После этого компилятор может быть уверен, что если вы поместите базовый экземпляр в свой метод, это будет фактически подклассом, который не является абстрактным и поэтому может быть инстанцирован.

Смежные вопросы