2

可能重复:
将派生类的 List<> 转换为基类的 List<>

标题可能没有什么意义。见代码:

class Person {}

class Manager : Person {}

class PaymentCalculator<T> where T : Person
{
    public double Calculate(T person)
    {
        return 0;    // calculate and return
    }
}

class Calculators : List<PaymentCalculator<Person>>
{
    public Calculators()
    {
        this.Add(new PaymentCalculator<Person>());
        this.Add(new PaymentCalculator<Manager>());     // this doesn't work

        PassCalculator(new PaymentCalculator<Person>());
        PassCalculator(new PaymentCalculator<Manager>());   // this doesn't work
    }

    public void PassCalculator(PaymentCalculator<Person> x)
    { }
}

代码中标记为“这不起作用”的两行将无法编译。

我可以解决这个问题,但我的意图似乎没有错。或者,是吗?

4

2 回答 2

1

没错。“默认情况下”new MyClass<Derived>()不可分配给new MyClass<Base>(). 但是您可以使用接口的协方差来解决问题:

class Person { }

class Manager : Person { }

interface IPaymentCalculator<out T> where T : Person
{
}

class PaymentCalculator<T> : IPaymentCalculator<T> where T : Person
{
    public double Calculate(T person)
    {
        return 0;    // calculate and return
    }
}

class Calculators : List<IPaymentCalculator<Person>>
{
    public Calculators()
    {
        this.Add(new PaymentCalculator<Person>());
        this.Add(new PaymentCalculator<Manager>());     // this doesn't work

        PassCalculator(new PaymentCalculator<Person>());
        PassCalculator(new PaymentCalculator<Manager>());   // this doesn't work
    }

    public void PassCalculator(IPaymentCalculator<Person> x)
    { }
}

这将编译并工作。

于 2012-09-07T18:24:14.120 回答
1

即使Manager继承自PersonPaymentCalculator<Manager>也不继承自PaymentCalculator<Person>。如果PaymentCalculator<T>contravariant,它会起作用,但类在 .NET 中不能是逆变的(只有接口和委托可以是逆变的)。

解决您的问题的一个可能方法是声明一个逆变接口,如下所示:

interface IPaymentCalculator<in T> // "in" means contravariant
{
    double Calculate(T person);
}

MakePaymentCalculator<T>实现IPaymentCalculator<T>接口:

class PaymentCalculator<T> : IPaymentCalculator<T> where T : Person
{
    public double Calculate(T person)
    {
        return 0;    // calculate and return
    }
}

并使Calculators类继承自List<IPaymentCalculator<Person>>

class Calculators : List<IPaymentCalculator<Person>>

通过这些更改,它应该可以按您的预期工作。

于 2012-09-07T18:26:07.630 回答