Может ли C# 4.0 помочь мне вызвать конструктор базового класса с upcast?
Я немного читал об общей дисперсии, и у меня пока нет полного понимания этого, но я хотел бы знать, делает ли это возможным что-то вроде следующего?
class A<T> { }
class B { }
class C : B { }
class My1 {
public My1(A<B> lessDerivedTemplateParameter)
{
}
}
class My2 : My1 {
public My2(A<C> moreDerivedTemplateParameter)
: base(moreDerivedTemplateParameter) // <-- compile error here, cannot convert
{
}
}
2 ответа
Решение
Нет, потому что пока C
наследуется от B
, A<C>
не наследуется от A<B>
,
Чтобы понять, почему это так, представьте, если A<T>
были вместо List<T>
:
class B { }
class C : B { }
class D : B { }
class My1 {
public My1(List<B> lessDerivedTemplateParameter)
{
// This is totally legal
lessDerivedTemplateParameter.Add(new D());
}
}
class My2 : My1 {
public My2(List<C> moreDerivedTemplateParameter)
// if this were allowed, then My1 could add a D to a list of Bs
: base(moreDerivedTemplateParameter)
{
}
}
Теперь, с другой стороны, это законно:
interface IA<out T> {
public T GetSome();
}
class B { }
class C : B { }
class D : B { }
class My1 {
public My1(IA<B> lessDerivedTemplateParameter)
{
// This is totally legal
var someB = lessDerivedTemplateParameter.GetSome();
}
}
class My2 : My1 {
public My2(IA<C> moreDerivedTemplateParameter)
// This is allowed, because an A<C> only *produces* C's (which are also B's)
// so the base class (which consumes B's, and doesnt care if they are C's)
// can use an IA<C>
: base(moreDerivedTemplateParameter)
{
}
}
Вы можете объявить A как интерфейс с параметром контравариантного типа, и он скомпилирует:
internal interface A<out T>
{
}
internal class B
{
}
internal class C : B
{
}
internal class My1
{
public My1(A<B> lessDerivedTemplateParameter)
{
}
}
internal class My2 : My1
{
public My2(A<C> moreDerivedTemplateParameter)
: base(moreDerivedTemplateParameter)
{
}
}