Ответ 1
Увы, вы должны явно указать тип
DoSomething<Derived>(d2);
теоретически невозможно создать нечто абстрактное
Здесь у нас есть простая иерархия классов и использование дженериков с ограничением типа 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
}
}
Код не удается скомпилировать в указанной строке с ошибкой:
'Base' должен быть не абстрактный тип с открытым конструктором без параметров, чтобы использовать его как параметр 'T' в родовом типе или методе 'Foo.DoSomething(T)'
Эта ошибка ясна и имеет смысл, но я надеялся, что компилятор поймет, что все производные от Base
(которые могут быть созданы в этой точке) имеют открытый конструктор без параметров.
Будет ли это теоретически возможным для компилятора?
Увы, вы должны явно указать тип
DoSomething<Derived>(d2);
теоретически невозможно создать нечто абстрактное
новое ограничение (ссылка на С#):
Чтобы использовать новое ограничение, тип не может быть абстрактным.
Призвание:
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
. После этого компилятор может быть уверен, что если вы поместите базовый экземпляр в свой метод, это будет фактически подклассом, который не является абстрактным и поэтому может быть создан.