来自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>();
}
}
}
此处DoctorMembers
为IPerson
,因此当我被要求IEnumerable
IPerson
时,我应该能够返回医生列表。
public IEnumerable<IPerson> Members
{
get
{
return DoctorMembers;
}
}
然而......编译器抱怨......为什么?我错过了什么?从语义上讲,这没有任何问题,到目前为止我使用的大多数OOP语言都可以在没有语法Pepto-Bismol的情况下消化它。我错过了一个关键字,以使编译器显而易见吗?
这里显而易见的捷径是LINQ将所有医生转换为IPerson
,但我不明白为什么这是必要的,甚至是可取的。
任何人都可以点亮我的灯笼吗?
答案 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>();
}
}