为什么这不编译?

时间:2012-11-04 17:08:58

标签: c# generics inheritance polymorphism

来自Java或Python我习惯于制作这样的结构,通常它“正常”。最近发现了C#,除了一些挫折之外,发现它很愉快。

一个这样的挫败感是我必须通过多态构造(覆盖,虚拟等)来控制它。

这是一个我还没有找到“只是做工作”的案例。

class Polymorphism
{
    public interface IPerson
    {
        String Name { get; set; }
    }

    public class Doctor : IPerson
    {
        public String Name { get; set; }
    }

    public class DoctorGroup
    {
        public IEnumerable<IPerson> Members
        {
            get
            {
                return DoctorMembers;
            }
        }

        public List<Doctor> DoctorMembers { get; set; }
        public DoctorGroup()
        {
            DoctorMembers = new List<Doctor>();
        }
    }
}

此处DoctorMembersIPerson,因此当我被要求IEnumerable IPerson时,我应该能够返回医生列表。

public IEnumerable<IPerson> Members
{
    get
    {
        return DoctorMembers;
    }
}

然而......编译器抱怨......为什么?我错过了什么?从语义上讲,这没有任何问题,到目前为止我使用的大多数OOP语言都可以在没有语法Pepto-Bismol的情况下消化它。我错过了一个关键字,以使编译器显而易见吗?

这里显而易见的捷径是LINQ将所有医生转换为IPerson,但我不明白为什么这是必要的,甚至是可取的。

任何人都可以点亮我的灯笼吗?

2 个答案:

答案 0 :(得分:10)

此代码使用针对.NET 4的C#4进行编译,但不会在C#3中编译,而C#3没有generic variance

基本上您需要从IEnumerable<Doctor>IEnumerable<IPerson>的隐式转换。这是安全的,因为你只能获得IEnumerable<T>的“值”...这就是为什么在.NET 4中,它被声明为IEnumerable<out T>

有关详细信息,请阅读有关泛型差异的更多信息,请记住,这仅适用于C#4及更高版本。

(如果你 使用C#3或.NET 3.5,你可以使用CSharpie显示的解决方案......但理想情况下,升级到更新的版本:)

答案 1 :(得分:3)

试试这个:

public IEnumerable<IPerson> Members
{
    get
    {
        return DoctorMembers.Cast<IPerson>();
    }
}