据我所知,在C#2.0中无法执行以下操作
public class Father { public virtual Father SomePropertyName { get { return this; } } } public class Child : Father { public override Child SomePropertyName { get { return this; } } }
我通过在派生类中将属性创建为"new"来解决问题,但当然这不是多态的.
public new Child SomePropertyName
2.0中有什么解决方案吗?3.5中解决此问题的任何功能如何?
您可以重新声明(新),但不能同时重新声明和覆盖(使用相同的名称).一种选择是使用受保护的方法来隐藏细节 - 这允许同时进行多态和隐藏:
public class Father { public Father SomePropertyName { get { return SomePropertyImpl(); } } protected virtual Father SomePropertyImpl() { // base-class version } } public class Child : Father { public new Child SomePropertyName { get { // since we know our local SomePropertyImpl actually returns a Child return (Child)SomePropertyImpl(); } } protected override Father SomePropertyImpl() { // do something different, might return a Child // but typed as Father for the return } }
由于类型安全问题,这在任何.NET语言中都是不可能的.在类型安全的语言中,您必须为返回值和参数的逆变提供协方差.拿这个代码:
class B { S Get(); Set(S); } class D : B { T Get(); Set(T); }
对于这些Get
方法,协方差意味着T
必须是S
或来自的类型S
.否则,如果你有一个类型对象的引用D
存储在一个类型的变量中B
,当你调用时,B.Get()
你不会得到一个可以表示为对象S
类型系统的对象.
对于这些Set
方法,逆变意味着T
必须是S
或S
来自的类型.否则,如果你有一个类型的对象的引用D
存储在一个类型的变量中B
,当你调用时B.Set(X)
,where X
类型S
但不是类型T
,D::Set(T)
将获得一个它没有预期的类型的对象.
在C#中,有意识地决定在重载属性时不允许更改类型,即使它们只有一个getter/setter对,因为否则会有非常不一致的行为("你的意思是,我可以更改类型一个有吸气剂,但没有吸气剂和二传手?为什么不呢?!?" - 匿名替代宇宙新手).
不,但您可以在2及以上版本中使用泛型:
public class MyClasswhere T: Person { public virtual T SomePropertyName { get { return ...; } } }
然后父亲和孩子是同一类的通用版本
来自维基百科:
在C#编程语言中,在该语言的2.0版本中添加了对委托的返回类型协方差和参数逆变的支持.方法覆盖不支持协方差或逆变.
尽管如此,它没有明确说明关于属性的协方差.